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