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 }