1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.rop.code; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.StdTypeList; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.TypeList; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.IntList; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.LabeledList; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * List of {@link BasicBlock} instances. 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class BasicBlockList extends LabeledList { 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code >= -1;} the count of registers required by this method or 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code -1} if not yet calculated 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int regCount; 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. All indices initially contain {@code null}, 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and the first-block label is initially {@code -1}. 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param size the size of the list 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public BasicBlockList(int size) { 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(size); 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul regCount = -1; 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs a mutable copy for {@code getMutableCopy()}. 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param old block to copy 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private BasicBlockList (BasicBlockList old) { 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(old); 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul regCount = old.regCount; 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the element at the given index. It is an error to call 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this with the index for an element which was never set; if you 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * do that, this will throw {@code NullPointerException}. 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n {@code >= 0, < size();} which index 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} element at that index 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public BasicBlock get(int n) { 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (BasicBlock) get0(n); 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Sets the basic block at the given index. 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n {@code >= 0, < size();} which index 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param bb {@code null-ok;} the element to set at {@code n} 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void set(int n, BasicBlock bb) { 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super.set(n, bb); 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Reset regCount, since it will need to be recalculated. 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul regCount = -1; 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns how many registers this method requires. This is simply 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the maximum of register-number-plus-category referred to by this 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance's instructions (indirectly through {@link BasicBlock} 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instances). 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the register count 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getRegCount() { 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (regCount == -1) { 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegCountVisitor visitor = new RegCountVisitor(); 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul forEachInsn(visitor); 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul regCount = visitor.getRegCount(); 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return regCount; 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the total instruction count for this instance. This is the 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * sum of the instruction counts of each block. 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the total instruction count 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getInstructionCount() { 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = size(); 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int result = 0; 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock one = (BasicBlock) getOrNull0(i); 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (one != null) { 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result += one.getInsns().size(); 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the total instruction count for this instance, ignoring 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * mark-local instructions which are not actually emitted. 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the total instruction count 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getEffectiveInstructionCount() { 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = size(); 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int result = 0; 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock one = (BasicBlock) getOrNull0(i); 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (one != null) { 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul InsnList insns = one.getInsns(); 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int insnsSz = insns.size(); 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int j = 0; j < insnsSz; j++) { 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Insn insn = insns.get(j); 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (insn.getOpcode().getOpcode() != RegOps.MARK_LOCAL) { 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result++; 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the first block in the list with the given label, if any. 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param label {@code >= 0;} the label to look for 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the so-labelled block 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IllegalArgumentException thrown if the label isn't found 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public BasicBlock labelToBlock(int label) { 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int idx = indexOfLabel(label); 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (idx < 0) { 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("no such label: " 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul + Hex.u2(label)); 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return get(idx); 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visits each instruction of each block in the list, in order. 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param visitor {@code non-null;} visitor to use 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void forEachInsn(Insn.Visitor visitor) { 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = size(); 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock one = get(i); 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul InsnList insns = one.getInsns(); 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul insns.forEach(visitor); 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is identical to this one, except that 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the registers in each instruction are offset by the given 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * amount. Mutability of the result is inherited from the 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * original. 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param delta the amount to offset register numbers by 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public BasicBlockList withRegisterOffset(int delta) { 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = size(); 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlockList result = new BasicBlockList(sz); 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock one = (BasicBlock) get0(i); 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (one != null) { 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.set(i, one.withRegisterOffset(delta)); 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (isImmutable()) { 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.setImmutable(); 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns a mutable copy of this list. 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public BasicBlockList getMutableCopy() { 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new BasicBlockList(this); 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the preferred successor for the given block. If the block 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * only has one successor, then that is the preferred successor. 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Otherwise, if the block has a primay successor, then that is 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the preferred successor. If the block has no successors, then 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this returns {@code null}. 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param block {@code non-null;} the block in question 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the preferred successor, if any 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public BasicBlock preferredSuccessorOf(BasicBlock block) { 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int primarySuccessor = block.getPrimarySuccessor(); 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList successors = block.getSuccessors(); 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int succSize = successors.size(); 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul switch (succSize) { 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 0: { 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 1: { 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return labelToBlock(successors.get(0)); 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (primarySuccessor != -1) { 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return labelToBlock(primarySuccessor); 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return labelToBlock(successors.get(0)); 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Compares the catches of two blocks for equality. This includes 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * both the catch types and target labels. 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param block1 {@code non-null;} one block to compare 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param block2 {@code non-null;} the other block to compare 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} if the two blocks' non-primary successors 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * are identical 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean catchesEqual(BasicBlock block1, 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock block2) { 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TypeList catches1 = block1.getExceptionHandlerTypes(); 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TypeList catches2 = block2.getExceptionHandlerTypes(); 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!StdTypeList.equalContents(catches1, catches2)) { 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList succ1 = block1.getSuccessors(); 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList succ2 = block2.getSuccessors(); 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = succ1.size(); // Both are guaranteed to be the same size. 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int primary1 = block1.getPrimarySuccessor(); 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int primary2 = block2.getPrimarySuccessor(); 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (((primary1 == -1) || (primary2 == -1)) 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && (primary1 != primary2)) { 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * For the current purpose, both blocks in question must 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * either both have a primary or both not have a primary to 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * be considered equal, and it turns out here that that's not 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the case. 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < size; i++) { 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int label1 = succ1.get(i); 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int label2 = succ2.get(i); 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (label1 == primary1) { 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * It should be the case that block2's primary is at the 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * same index. If not, we consider the blocks unequal for 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the current purpose. 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (label2 != primary2) { 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (label1 != label2) { 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return true; 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Instruction visitor class for counting registers used. 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static class RegCountVisitor 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul implements Insn.Visitor { 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} register count in-progress */ 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int regCount; 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegCountVisitor() { 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul regCount = 0; 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the register count. 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the count 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getRegCount() { 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return regCount; 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainInsn(PlainInsn insn) { 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul visit(insn); 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainCstInsn(PlainCstInsn insn) { 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul visit(insn); 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitSwitchInsn(SwitchInsn insn) { 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul visit(insn); 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingCstInsn(ThrowingCstInsn insn) { 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul visit(insn); 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingInsn(ThrowingInsn insn) { 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul visit(insn); 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitFillArrayDataInsn(FillArrayDataInsn insn) { 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul visit(insn); 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for all the {@code visit*} methods. 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} instruction being visited 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void visit(Insn insn) { 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec result = insn.getResult(); 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (result != null) { 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul processReg(result); 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList sources = insn.getSources(); 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = sources.size(); 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul processReg(sources.get(i)); 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Processes the given register spec. 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param spec {@code non-null;} the register spec 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void processReg(RegisterSpec spec) { 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int reg = spec.getNextReg(); 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (reg > regCount) { 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul regCount = reg; 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 399