1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.code; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpec; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpecSet; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType; 22333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.FixedSizeList; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintStream; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * List of local variables. Each local variable entry indicates a 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * range of code which it is valid for, a register number, a name, 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and a type. 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class LocalList extends FixedSizeList { 3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} empty instance */ 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static final LocalList EMPTY = new LocalList(0); 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** whether to run the self-check code */ 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final boolean DEBUG = false; 41f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 4399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Constructs an instance. All indices initially contain {@code null}. 44f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 4599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param size {@code >= 0;} the size of the list 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public LocalList(int size) { 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(size); 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the element at the given index. It is an error to call 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this with the index for an element which was never set; if you 5499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * do that, this will throw {@code NullPointerException}. 55f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param n {@code >= 0, < size();} which index 5799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} element at that index 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Entry get(int n) { 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (Entry) get0(n); 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the entry at the given index. 65f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param n {@code >= 0, < size();} which index 6799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param entry {@code non-null;} the entry to set at {@code n} 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void set(int n, Entry entry) { 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project set0(n, entry); 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Does a human-friendly dump of this instance. 75f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param out {@code non-null;} where to dump 7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param prefix {@code non-null;} prefix to attach to each line of output 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void debugPrint(PrintStream out, String prefix) { 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = size(); 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.print(prefix); 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.println(get(i)); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Disposition of a local entry. 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static enum Disposition { 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** local started (introduced) */ 93f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein START, 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** local ended without being replaced */ 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project END_SIMPLY, 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** local ended because it was directly replaced */ 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project END_REPLACED, 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** local ended because it was moved to a different register */ 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project END_MOVED, 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * local ended because the previous local clobbered this one 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (because it is category-2) 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project END_CLOBBERED_BY_PREV, 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * local ended because the next local clobbered this one 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (because this one is a category-2) 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project END_CLOBBERED_BY_NEXT; 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entry in a local list. 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static class Entry implements Comparable<Entry> { 12199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code >= 0;} address */ 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final int address; 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} disposition of the local */ 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final Disposition disposition; 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} register spec representing the variable */ 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final RegisterSpec spec; 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 13099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} variable type (derived from {@code spec}) */ 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final CstType type; 132f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 135f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 136f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * @param address {@code >= 0;} address 13799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param disposition {@code non-null;} disposition of the local 1384b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * @param spec {@code non-null;} register spec representing 1394b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * the variable 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Entry(int address, Disposition disposition, RegisterSpec spec) { 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address < 0) { 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("address < 0"); 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (disposition == null) { 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("disposition == null"); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (spec.getLocalItem() == null) { 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException( 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "spec.getLocalItem() == null"); 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (NullPointerException ex) { 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Elucidate the exception. 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("spec == null"); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.address = address; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.disposition = disposition; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.spec = spec; 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.type = CstType.intern(spec.getType()); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String toString() { 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return Integer.toHexString(address) + " " + disposition + " " + 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project spec; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean equals(Object other) { 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!(other instanceof Entry)) { 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (compareTo((Entry) other) == 0); 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compares by (in priority order) address, end then start 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * disposition (variants of end are all consistered 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * equivalent), and spec. 185f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param other {@code non-null;} entry to compare to 18799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code -1..1;} standard result of comparison 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int compareTo(Entry other) { 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address < other.address) { 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (address > other.address) { 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean thisIsStart = isStart(); 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean otherIsStart = other.isStart(); 198f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thisIsStart != otherIsStart) { 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return thisIsStart ? 1 : -1; 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return spec.compareTo(other.spec); 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the address. 208f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 20999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 0;} the address 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getAddress() { 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return address; 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the disposition. 217f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 21899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the disposition 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Disposition getDisposition() { 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return disposition; 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets whether this is a local start. This is just shorthand for 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code getDisposition() == Disposition.START}. 227f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {@code true} iff this is a start 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean isStart() { 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return disposition == Disposition.START; 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the variable name. 236f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 23799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code null-ok;} the variable name 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 239333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson public CstString getName() { 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return spec.getLocalItem().getName(); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the variable signature. 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 24699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code null-ok;} the variable signature 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 248333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson public CstString getSignature() { 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return spec.getLocalItem().getSignature(); 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the variable's type. 254f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 25599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the type 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public CstType getType() { 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return type; 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the number of the register holding the variable. 263f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 2644b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * @return {@code >= 0;} the number of the register holding 2654b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * the variable 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getRegister() { 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return spec.getReg(); 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the RegisterSpec of the register holding the variable. 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 27499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} RegisterSpec of the holding register. 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public RegisterSpec getRegisterSpec() { 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return spec; 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns whether or not this instance matches the given spec. 282f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 28392f4f58df944fd10c77e3d39d200c38c1491a941Jean-Baptiste Queru * @param otherSpec {@code non-null;} the spec in question 28499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code true} iff this instance matches 28599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code spec} 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean matches(RegisterSpec otherSpec) { 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return spec.equalsUsingSimpleType(otherSpec); 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns whether or not this instance matches the spec in 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the given instance. 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 29599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param other {@code non-null;} another entry 29699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code true} iff this instance's spec matches 29799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code other} 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean matches(Entry other) { 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return matches(other.spec); 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns an instance just like this one but with the disposition 305f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * set as given. 306f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 30799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param disposition {@code non-null;} the new disposition 30899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} an appropriately-constructed instance 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Entry withDisposition(Disposition disposition) { 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (disposition == this.disposition) { 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return this; 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 314f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return new Entry(address, disposition, spec); 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 318f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance for the given method, based on the given 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * block order and intermediate local information. 322f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 32399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param insns {@code non-null;} instructions to convert 324f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * @return {@code non-null;} the constructed list 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static LocalList make(DalvInsnList insns) { 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = insns.size(); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Go through the insn list, looking for all the local 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * variable pseudoinstructions, splitting out LocalSnapshots 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into separate per-variable starts, adding explicit ends 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * wherever a variable is replaced or moved, and collecting 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * these and all the other local variable "activity" 335f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * together into an output list (without the other insns). 336f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note: As of this writing, this method won't be handed any 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * insn lists that contain local ends, but I (danfuzz) expect 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that to change at some point, when we start feeding that 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * info explicitly into the rop layer rather than only trying 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to infer it. So, given that expectation, this code is 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * written to deal with them. 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MakeState state = new MakeState(sz); 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DalvInsn insn = insns.get(i); 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (insn instanceof LocalSnapshot) { 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpecSet snapshot = 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ((LocalSnapshot) insn).getLocals(); 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project state.snapshot(insn.getAddress(), snapshot); 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (insn instanceof LocalStart) { 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec local = ((LocalStart) insn).getLocal(); 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project state.startLocal(insn.getAddress(), local); 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (insn instanceof LocalEnd) { 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec local = ((LocalEnd) insn).getLocal(); 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project state.endLocal(insn.getAddress(), local); 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LocalList result = state.finish(); 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (DEBUG) { 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project debugVerify(result); 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Debugging helper that verifies the constraint that a list doesn't 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contain any redundant local starts and that local ends that are 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * due to replacements are properly annotated. 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static void debugVerify(LocalList locals) { 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project debugVerify0(locals); 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = locals.size(); 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.err.println(locals.get(i)); 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ex; 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 387f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 389f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for {@link #debugVerify} which does most of the work. 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static void debugVerify0(LocalList locals) { 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = locals.size(); 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry[] active = new Entry[65536]; 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry e = locals.get(i); 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int reg = e.getRegister(); 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (e.isStart()) { 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry already = active[reg]; 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((already != null) && e.matches(already)) { 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("redundant start at " + 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Integer.toHexString(e.getAddress()) + ": got " + 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project e + "; had " + already); 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project active[reg] = e; 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (active[reg] == null) { 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("redundant end at " + 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Integer.toHexString(e.getAddress())); 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 416f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int addr = e.getAddress(); 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean foundStart = false; 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int j = i + 1; j < sz; j++) { 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry test = locals.get(j); 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (test.getAddress() != addr) { 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (test.getRegisterSpec().getReg() == reg) { 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (test.isStart()) { 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (e.getDisposition() 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project != Disposition.END_REPLACED) { 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException( 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "improperly marked end at " + 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Integer.toHexString(addr)); 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project foundStart = true; 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException( 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "redundant end at " + 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Integer.toHexString(addr)); 438f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein } 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!foundStart && 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (e.getDisposition() == Disposition.END_REPLACED)) { 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException( 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "improper end replacement claim at " + 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Integer.toHexString(addr)); 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 448f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project active[reg] = null; 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Intermediate state when constructing a local list. 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static class MakeState { 45899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} result being collected */ 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ArrayList<Entry> result; 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 46299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code >= 0;} running count of nulled result entries, to help with 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sizing the final list 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int nullResultCount; 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code null-ok;} current register mappings */ 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private RegisterSpecSet regs; 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code null-ok;} result indices where local ends are stored */ 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int[] endIndices; 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code >= 0;} last address seen */ 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int lastAddress; 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public MakeState(int initialSize) { 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = new ArrayList<Entry>(initialSize); 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nullResultCount = 0; 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regs = null; 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endIndices = null; 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lastAddress = 0; 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks the address and other vitals as a prerequisite to 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * further processing. 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 49199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param address {@code >= 0;} address about to be processed 49299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param reg {@code >= 0;} register number about to be processed 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void aboutToProcess(int address, int reg) { 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean first = (endIndices == null); 496f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((address == lastAddress) && !first) { 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address < lastAddress) { 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("shouldn't happen"); 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (first || (reg >= endIndices.length)) { 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is the first allocation of the state set and 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * index array, or we need to grow. (The latter doesn't 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * happen much; in fact, we have only ever observed 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it happening in test cases, never in "real" code.) 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int newSz = reg + 1; 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpecSet newRegs = new RegisterSpecSet(newSz); 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int[] newEnds = new int[newSz]; 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Arrays.fill(newEnds, -1); 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!first) { 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newRegs.putAll(regs); 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(endIndices, 0, newEnds, 0, 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endIndices.length); 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regs = newRegs; 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endIndices = newEnds; 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the local state at the given address to the given snapshot. 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The first call on this instance must be to this method, so that 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the register state can be properly sized. 532f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 53399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param address {@code >= 0;} the address 53499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param specs {@code non-null;} spec set representing the locals 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void snapshot(int address, RegisterSpecSet specs) { 537f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein if (DEBUG) { 538f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein System.err.printf("%04x snapshot %s\n", address, specs); 539f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein } 540f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = specs.getMaxSize(); 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aboutToProcess(address, sz - 1); 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec oldSpec = regs.get(i); 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec newSpec = filterSpec(specs.get(i)); 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (oldSpec == null) { 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newSpec != null) { 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project startLocal(address, newSpec); 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (newSpec == null) { 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endLocal(address, oldSpec); 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (! newSpec.equalsUsingSimpleType(oldSpec)) { 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endLocal(address, oldSpec); 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project startLocal(address, newSpec); 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 559f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 560f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein if (DEBUG) { 561f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein System.err.printf("%04x snapshot done\n", address); 562f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein } 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 564f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Starts a local at the given address. 567f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 56899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param address {@code >= 0;} the address 5694b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * @param startedLocal {@code non-null;} spec representing the 5704b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * started local 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void startLocal(int address, RegisterSpec startedLocal) { 573f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein if (DEBUG) { 574f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein System.err.printf("%04x start %s\n", address, startedLocal); 575f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein } 576f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int regNum = startedLocal.getReg(); 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project startedLocal = filterSpec(startedLocal); 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aboutToProcess(address, regNum); 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec existingLocal = regs.get(regNum); 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (startedLocal.equalsUsingSimpleType(existingLocal)) { 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Silently ignore a redundant start. 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec movedLocal = regs.findMatchingLocal(startedLocal); 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (movedLocal != null) { 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The same variable was moved from one register to another. 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * So add an end for its old location. 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project addOrUpdateEnd(address, Disposition.END_MOVED, movedLocal); 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int endAt = endIndices[regNum]; 599f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (existingLocal != null) { 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is an existing (but non-matching) local. 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add an explicit end for it. 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project add(address, Disposition.END_REPLACED, existingLocal); 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (endAt >= 0) { 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look for an end local for the same register at the 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * same address. If found, then update it or delete 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it, depending on whether or not it represents the 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * same variable as the one being started. 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry endEntry = result.get(endAt); 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (endEntry.getAddress() == address) { 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (endEntry.matches(startedLocal)) { 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There was already an end local for the same 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * variable at the same address. This turns 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * out to be superfluous, as we are starting 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * up the exact same local. This situation can 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * happen when a single local variable got 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * somehow "split up" during intermediate 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * processing. In any case, rather than represent 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the end-then-start, just remove the old end. 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.set(endAt, null); 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nullResultCount++; 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regs.put(startedLocal); 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endIndices[regNum] = -1; 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There was a different variable ended at the 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * same address. Update it to indicate that 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it was ended due to a replacement (rather than 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ending for no particular reason). 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endEntry = endEntry.withDisposition( 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Disposition.END_REPLACED); 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.set(endAt, endEntry); 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 644f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 645f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein /* 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The code above didn't find and remove an unnecessary 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * local end, so we now have to add one or more entries to 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the output to capture the transition. 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the local just below (in the register set at reg-1) 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is of category-2, then it is ended by this new start. 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (regNum > 0) { 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec justBelow = regs.get(regNum - 1); 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((justBelow != null) && justBelow.isCategory2()) { 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project addOrUpdateEnd(address, 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Disposition.END_CLOBBERED_BY_NEXT, 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project justBelow); 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Similarly, if this local is category-2, then the local 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * just above (if any) is ended by the start now being 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * emitted. 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (startedLocal.isCategory2()) { 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec justAbove = regs.get(regNum + 1); 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (justAbove != null) { 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project addOrUpdateEnd(address, 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Disposition.END_CLOBBERED_BY_PREV, 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project justAbove); 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: Add an end for the same local in a different reg, 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if any (that is, if the local migrates from vX to vY, 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we should note that as a local end in vX). 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 683f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project add(address, Disposition.START, startedLocal); 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 688f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * Ends a local at the given address, using the disposition 689f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * {@code END_SIMPLY}. 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 69199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param address {@code >= 0;} the address 6924b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * @param endedLocal {@code non-null;} spec representing the 6934b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * local being ended 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void endLocal(int address, RegisterSpec endedLocal) { 696f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein endLocal(address, endedLocal, Disposition.END_SIMPLY); 697f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein } 698f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 699f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein /** 700f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * Ends a local at the given address. 701f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 702f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * @param address {@code >= 0;} the address 703f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * @param endedLocal {@code non-null;} spec representing the 704f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * local being ended 705f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * @param disposition reason for the end 706f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein */ 707f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein public void endLocal(int address, RegisterSpec endedLocal, 708f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein Disposition disposition) { 709f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein if (DEBUG) { 710f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein System.err.printf("%04x end %s\n", address, endedLocal); 711f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein } 712f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int regNum = endedLocal.getReg(); 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endedLocal = filterSpec(endedLocal); 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aboutToProcess(address, regNum); 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int endAt = endIndices[regNum]; 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (endAt >= 0) { 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The local in the given register is already ended. 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Silently return without adding anything to the result. 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Check for start and end at the same address. 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (checkForEmptyRange(address, endedLocal)) { 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 733f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein add(address, disposition, endedLocal); 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for {@link #endLocal}, which handles the cases where 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and end local is issued at the same address as a start local 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for the same register. If this case is found, then this 740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method will remove the start (as the local was never actually 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * active), update the {@link #endIndices} to be accurate, and 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if needed update the newly-active end to reflect an altered 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * disposition. 744f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 74599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param address {@code >= 0;} the address 7464b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * @param endedLocal {@code non-null;} spec representing the 7474b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein * local being ended 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {@code true} iff this method found the case in question 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and adjusted things accordingly 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean checkForEmptyRange(int address, 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec endedLocal) { 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = result.size() - 1; 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry entry; 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Look for a previous entry at the same address. 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (/*at*/; at >= 0; at--) { 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project entry = result.get(at); 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (entry == null) { 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (entry.getAddress() != address) { 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // We didn't find any match at the same address. 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (entry.matches(endedLocal)) { 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In fact, we found that the endedLocal had started at the 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * same address, so do all the requisite cleanup. 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 778f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regs.remove(endedLocal); 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.set(at, null); 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nullResultCount++; 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int regNum = endedLocal.getReg(); 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean found = false; 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project entry = null; 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Now look back further to update where the register ended. 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (at--; at >= 0; at--) { 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project entry = result.get(at); 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (entry == null) { 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (entry.getRegisterSpec().getReg() == regNum) { 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project found = true; 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (found) { 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // We found an end for the same register. 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endIndices[regNum] = at; 804f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (entry.getAddress() == address) { 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's still the same address, so update the 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * disposition. 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.set(at, 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project entry.withDisposition(Disposition.END_SIMPLY)); 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Converts a given spec into the form acceptable for use in a 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * local list. This, in particular, transforms the "known 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * null" type into simply {@code Object}. This method needs to 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be called for any spec that is on its way into a locals 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list. 824f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>This isn't necessarily the cleanest way to achieve the 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * goal of not representing known nulls in a locals list, but 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it gets the job done.</p> 828f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 82999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param orig {@code null-ok;} the original spec 83099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code null-ok;} an appropriately modified spec, or the 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * original if nothing needs to be done 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static RegisterSpec filterSpec(RegisterSpec orig) { 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((orig != null) && (orig.getType() == Type.KNOWN_NULL)) { 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return orig.withType(Type.OBJECT); 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return orig; 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Adds an entry to the result, updating the adjunct tables 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * accordingly. 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 84599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param address {@code >= 0;} the address 84699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param disposition {@code non-null;} the disposition 84799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param spec {@code non-null;} spec representing the local 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void add(int address, Disposition disposition, 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec spec) { 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int regNum = spec.getReg(); 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.add(new Entry(address, disposition, spec)); 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (disposition == Disposition.START) { 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regs.put(spec); 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endIndices[regNum] = -1; 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regs.remove(spec); 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endIndices[regNum] = result.size() - 1; 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 865f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * Adds or updates an end local (changing its disposition). If 866f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * this would cause an empty range for a local, this instead 867f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * removes the local entirely. 868f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 86999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param address {@code >= 0;} the address 87099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param disposition {@code non-null;} the disposition 87199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param spec {@code non-null;} spec representing the local 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void addOrUpdateEnd(int address, Disposition disposition, 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterSpec spec) { 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (disposition == Disposition.START) { 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("shouldn't happen"); 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int regNum = spec.getReg(); 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int endAt = endIndices[regNum]; 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (endAt >= 0) { 883f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein // There is a previous end. 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry endEntry = result.get(endAt); 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((endEntry.getAddress() == address) && 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endEntry.getRegisterSpec().equals(spec)) { 887f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein /* 888f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * The end is for the right address and variable, so 889f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * update it. 890f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein */ 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.set(endAt, endEntry.withDisposition(disposition)); 892f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein regs.remove(spec); // TODO: Is this line superfluous? 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 896f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 897f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein endLocal(address, spec, disposition); 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Finishes processing altogether and gets the result. 902f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein * 90399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the result list 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public LocalList finish() { 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aboutToProcess(Integer.MAX_VALUE, 0); 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int resultSz = result.size(); 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int finalSz = resultSz - nullResultCount; 910f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (finalSz == 0) { 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return EMPTY; 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Collect an array of only the non-null entries, and then 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sort it to get a consistent order for everything: Local 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ends and starts for a given address could come in any 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * order, but we want ends before starts as well as 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * registers in order (within ends or starts). 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Entry[] resultArr = new Entry[finalSz]; 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (resultSz == finalSz) { 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.toArray(resultArr); 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = 0; 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (Entry e : result) { 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (e != null) { 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project resultArr[at++] = e; 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Arrays.sort(resultArr); 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LocalList resultList = new LocalList(finalSz); 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < finalSz; i++) { 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project resultList.set(i, resultArr[i]); 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project resultList.setImmutable(); 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return resultList; 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 947f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein } 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 949