1 /* 2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.openjdk.asmtools.jasm; 24 25 import java.io.IOException; 26 import java.util.ArrayList; 27 28 /** 29 * 30 */ 31 class SwitchTable { 32 33 Argument deflabel = null; 34 ArrayList<Argument> labels = new ArrayList<>(); 35 ArrayList<Integer> keys = new ArrayList<>(); 36 37 // for tableswitch: 38 Argument[] resLabels; 39 int high, low; 40 41 int pc, pad; 42 Environment env; 43 44 SwitchTable(Environment env) { 45 this.env = env; 46 } 47 48 void addEntry(int key, Argument label) { 49 keys.add(key); 50 labels.add(label); 51 } 52 53 // for lookupswitch: 54 int calcLookupSwitch(int pc) { 55 this.pc = pc; 56 pad = ((3 - pc) & 0x3); 57 int len = 1 + pad + (keys.size() + 1) * 8; 58 if (deflabel == null) { 59 deflabel = new Argument(pc + len); 60 } 61 return len; 62 } 63 64 void writeLookupSwitch(CheckedDataOutputStream out) throws IOException { 65 env.traceln(" writeLookupSwitch: pc=" + pc + " pad=" + pad + " deflabel=" + deflabel.arg); 66 int k; 67 for (k = 0; k < pad; k++) { 68 out.writeByte(0); 69 } 70 out.writeInt(deflabel.arg - pc); 71 out.writeInt(keys.size()); 72 for (k = 0; k < keys.size(); k++) { 73 out.writeInt(keys.get(k)); 74 out.writeInt((labels.get(k)).arg - pc); 75 } 76 } 77 78 int recalcTableSwitch(int pc) { 79 int k; 80 int numpairs = keys.size(); 81 int high1 = Integer.MIN_VALUE, low1 = Integer.MAX_VALUE; 82 int numslots = 0; 83 if (numpairs > 0) { 84 for (k = 0; k < numpairs; k++) { 85 int key = keys.get(k); 86 if (key > high1) { 87 high1 = key; 88 } 89 if (key < low1) { 90 low1 = key; 91 } 92 } 93 numslots = high1 - low1 + 1; 94 } 95 // if (numslots>2000) env.error("long.switchtable", "2000"); 96 env.traceln(" recalcTableSwitch: low=" + low1 + " high=" + high1); 97 this.pc = pc; 98 pad = ((3 - pc) & 0x3); 99 int len = 1 + pad + (numslots + 3) * 4; 100 if (deflabel == null) { 101 deflabel = new Argument(pc + len); 102 } 103 Argument[] resLabels1 = new Argument[numslots]; 104 for (k = 0; k < numslots; k++) { 105 resLabels1[k] = deflabel; 106 } 107 for (k = 0; k < numpairs; k++) { 108 env.traceln(" keys.data[" + k + "]=" + keys.get(k)); 109 resLabels1[keys.get(k) - low1] = labels.get(k); 110 } 111 this.resLabels = resLabels1; 112 this.labels = null; 113 this.keys = null; 114 this.high = high1; 115 this.low = low1; 116 return len; 117 } 118 119 void writeTableSwitch(CheckedDataOutputStream out) throws IOException { 120 int k; 121 for (k = 0; k < pad; k++) { 122 out.writeByte(0); 123 } 124 out.writeInt(deflabel.arg - pc); 125 out.writeInt(low); 126 out.writeInt(high); 127 for (k = 0; k < resLabels.length; k++) { 128 out.writeInt(resLabels[k].arg - pc); 129 } 130 } 131 }