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.dex.code; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpecList; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.SourcePosition; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.IntList; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Pseudo-instruction which holds switch data. The switch data is 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * a map of values to target addresses, and this class writes the data 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in either a "packed" or "sparse" form. 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class SwitchData extends VariableSizeInsn { 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} address representing the instruction that uses this 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final CodeAddress user; 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} sorted list of switch cases (keys) */ 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final IntList cases; 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} corresponding list of code addresses; the branch 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * target for each case 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final CodeAddress[] targets; 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** whether the output table will be packed (vs. sparse) */ 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final boolean packed; 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. The output address of this instance is initially 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * unknown ({@code -1}). 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param position {@code non-null;} source position 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param user {@code non-null;} address representing the instruction that 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * uses this instance 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param cases {@code non-null;} sorted list of switch cases (keys) 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param targets {@code non-null;} corresponding list of code addresses; the 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * branch target for each case 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public SwitchData(SourcePosition position, CodeAddress user, 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList cases, CodeAddress[] targets) { 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(position, RegisterSpecList.EMPTY); 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (user == null) { 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("user == null"); 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (cases == null) { 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("cases == null"); 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (targets == null) { 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("targets == null"); 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = cases.size(); 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sz != targets.length) { 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("cases / targets mismatch"); 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sz > 65535) { 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("too many cases"); 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.user = user; 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.cases = cases; 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.targets = targets; 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.packed = shouldPack(cases); 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int codeSize() { 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return packed ? (int) packedCodeSize(cases) : 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (int) sparseCodeSize(cases); 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void writeTo(AnnotatedOutput out) { 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int baseAddress = user.getAddress(); 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int defaultTarget = Dops.PACKED_SWITCH.getFormat().codeSize(); 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = targets.length; 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (packed) { 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int firstCase = (sz == 0) ? 0 : cases.get(0); 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int lastCase = (sz == 0) ? 0 : cases.get(sz - 1); 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int outSz = lastCase - firstCase + 1; 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(0x100 | DalvOps.NOP); 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(outSz); 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeInt(firstCase); 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int caseAt = 0; 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < outSz; i++) { 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int outCase = firstCase + i; 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int oneCase = cases.get(caseAt); 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int relTarget; 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (oneCase > outCase) { 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul relTarget = defaultTarget; 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul relTarget = targets[caseAt].getAddress() - baseAddress; 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul caseAt++; 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeInt(relTarget); 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(0x200 | DalvOps.NOP); 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(sz); 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeInt(cases.get(i)); 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int relTarget = targets[i].getAddress() - baseAddress; 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeInt(relTarget); 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public DalvInsn withRegisters(RegisterSpecList registers) { 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new SwitchData(getPosition(), user, cases, targets); 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns whether or not this instance's data will be output as packed. 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff the data is to be packed 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean isPacked() { 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return packed; 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected String argString() { 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(100); 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = targets.length; 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("\n "); 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(cases.get(i)); 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(": "); 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(targets[i]); 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected String listingString0(boolean noteIndices) { 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int baseAddress = user.getAddress(); 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(100); 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = targets.length; 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(packed ? "packed" : "sparse"); 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("-switch-data // for switch @ "); 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(Hex.u2(baseAddress)); 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int absTarget = targets[i].getAddress(); 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int relTarget = absTarget - baseAddress; 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("\n "); 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(cases.get(i)); 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(": "); 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(Hex.u4(absTarget)); 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" // "); 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(Hex.s4(relTarget)); 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the size of a packed table for the given cases, in 16-bit code 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * units. 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param cases {@code non-null;} sorted list of cases 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= -1;} the packed table size or {@code -1} if the 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * cases couldn't possibly be represented as a packed table 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static long packedCodeSize(IntList cases) { 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = cases.size(); 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul long low = cases.get(0); 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul long high = cases.get(sz - 1); 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul long result = ((high - low + 1)) * 2 + 4; 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (result <= 0x7fffffff) ? result : -1; 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the size of a sparse table for the given cases, in 16-bit code 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * units. 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param cases {@code non-null;} sorted list of cases 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code > 0;} the sparse table size 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static long sparseCodeSize(IntList cases) { 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = cases.size(); 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (sz * 4L) + 2; 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Determines whether the given list of cases warrant being packed. 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param cases {@code non-null;} sorted list of cases 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff the table encoding the cases 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * should be packed 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static boolean shouldPack(IntList cases) { 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = cases.size(); 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sz < 2) { 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return true; 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul long packedSize = packedCodeSize(cases); 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul long sparseSize = sparseCodeSize(cases); 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * We pick the packed representation if it is possible and 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * would be as small or smaller than 5/4 of the sparse 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * representation. That is, we accept some size overhead on 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the packed representation, since that format is faster to 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * execute at runtime. 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (packedSize >= 0) && (packedSize <= ((sparseSize * 5) / 4)); 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 258