author | joehw |
Mon, 17 Apr 2017 16:24:10 -0700 | |
changeset 44797 | 8b3b3b911b8a |
parent 25868 | 686eef1e7a79 |
child 46174 | 5611d2529b49 |
permissions | -rw-r--r-- |
6 | 1 |
/* |
2 |
* reserved comment block |
|
3 |
* DO NOT REMOVE OR ALTER! |
|
4 |
*/ |
|
44797
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
5 |
/* |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
6 |
* Licensed to the Apache Software Foundation (ASF) under one or more |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
7 |
* contributor license agreements. See the NOTICE file distributed with |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
8 |
* this work for additional information regarding copyright ownership. |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
9 |
* The ASF licenses this file to You under the Apache License, Version 2.0 |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
10 |
* (the "License"); you may not use this file except in compliance with |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
11 |
* the License. You may obtain a copy of the License at |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
12 |
* |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
13 |
* http://www.apache.org/licenses/LICENSE-2.0 |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
14 |
* |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
15 |
* Unless required by applicable law or agreed to in writing, software |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
16 |
* distributed under the License is distributed on an "AS IS" BASIS, |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
17 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
18 |
* See the License for the specific language governing permissions and |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
19 |
* limitations under the License. |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
20 |
*/ |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
21 |
|
6 | 22 |
package com.sun.org.apache.bcel.internal.generic; |
23 |
||
24 |
import java.io.*; |
|
25 |
import com.sun.org.apache.bcel.internal.util.ByteSequence; |
|
26 |
||
27 |
/** |
|
28 |
* Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions. |
|
29 |
* |
|
30 |
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> |
|
31 |
* @see LOOKUPSWITCH |
|
32 |
* @see TABLESWITCH |
|
33 |
* @see InstructionList |
|
34 |
*/ |
|
35 |
public abstract class Select extends BranchInstruction |
|
36 |
implements VariableLengthInstruction, StackProducer |
|
37 |
{ |
|
38 |
protected int[] match; // matches, i.e., case 1: ... |
|
39 |
protected int[] indices; // target offsets |
|
40 |
protected InstructionHandle[] targets; // target objects in instruction list |
|
41 |
protected int fixed_length; // fixed length defined by subclasses |
|
42 |
protected int match_length; // number of cases |
|
43 |
protected int padding = 0; // number of pad bytes for alignment |
|
44 |
||
45 |
/** |
|
46 |
* Empty constructor needed for the Class.newInstance() statement in |
|
47 |
* Instruction.readInstruction(). Not to be used otherwise. |
|
48 |
*/ |
|
49 |
Select() {} |
|
50 |
||
51 |
/** |
|
52 |
* (Match, target) pairs for switch. |
|
53 |
* `Match' and `targets' must have the same length of course. |
|
54 |
* |
|
55 |
* @param match array of matching values |
|
56 |
* @param targets instruction targets |
|
57 |
* @param target default instruction target |
|
58 |
*/ |
|
59 |
Select(short opcode, int[] match, InstructionHandle[] targets, |
|
60 |
InstructionHandle target) { |
|
61 |
super(opcode, target); |
|
62 |
||
63 |
this.targets = targets; |
|
17538 | 64 |
for(int i=0; i < targets.length; i++) { |
65 |
BranchInstruction.notifyTargetChanged(targets[i], this); |
|
66 |
} |
|
6 | 67 |
|
68 |
this.match = match; |
|
69 |
||
70 |
if((match_length = match.length) != targets.length) |
|
71 |
throw new ClassGenException("Match and target array have not the same length"); |
|
72 |
||
73 |
indices = new int[match_length]; |
|
74 |
} |
|
75 |
||
76 |
/** |
|
77 |
* Since this is a variable length instruction, it may shift the following |
|
78 |
* instructions which then need to update their position. |
|
79 |
* |
|
80 |
* Called by InstructionList.setPositions when setting the position for every |
|
81 |
* instruction. In the presence of variable length instructions `setPositions' |
|
82 |
* performs multiple passes over the instruction list to calculate the |
|
83 |
* correct (byte) positions and offsets by calling this function. |
|
84 |
* |
|
85 |
* @param offset additional offset caused by preceding (variable length) instructions |
|
86 |
* @param max_offset the maximum offset that may be caused by these instructions |
|
87 |
* @return additional offset caused by possible change of this instruction's length |
|
88 |
*/ |
|
17538 | 89 |
@Override |
6 | 90 |
protected int updatePosition(int offset, int max_offset) { |
91 |
position += offset; // Additional offset caused by preceding SWITCHs, GOTOs, etc. |
|
92 |
||
93 |
short old_length = length; |
|
94 |
||
95 |
/* Alignment on 4-byte-boundary, + 1, because of tag byte. |
|
96 |
*/ |
|
97 |
padding = (4 - ((position + 1) % 4)) % 4; |
|
98 |
length = (short)(fixed_length + padding); // Update length |
|
99 |
||
100 |
return length - old_length; |
|
101 |
} |
|
102 |
||
103 |
/** |
|
104 |
* Dump instruction as byte code to stream out. |
|
105 |
* @param out Output stream |
|
106 |
*/ |
|
17538 | 107 |
@Override |
6 | 108 |
public void dump(DataOutputStream out) throws IOException { |
109 |
out.writeByte(opcode); |
|
110 |
||
111 |
for(int i=0; i < padding; i++) // Padding bytes |
|
112 |
out.writeByte(0); |
|
113 |
||
114 |
index = getTargetOffset(); // Write default target offset |
|
115 |
out.writeInt(index); |
|
116 |
} |
|
117 |
||
118 |
/** |
|
119 |
* Read needed data (e.g. index) from file. |
|
120 |
*/ |
|
17538 | 121 |
@Override |
6 | 122 |
protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException |
123 |
{ |
|
124 |
padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes |
|
125 |
||
126 |
for(int i=0; i < padding; i++) { |
|
127 |
bytes.readByte(); |
|
128 |
} |
|
129 |
||
130 |
// Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH) |
|
131 |
index = bytes.readInt(); |
|
132 |
} |
|
133 |
||
134 |
/** |
|
135 |
* @return mnemonic for instruction |
|
136 |
*/ |
|
17538 | 137 |
@Override |
6 | 138 |
public String toString(boolean verbose) { |
17538 | 139 |
final StringBuilder buf = new StringBuilder(super.toString(verbose)); |
6 | 140 |
|
141 |
if(verbose) { |
|
142 |
for(int i=0; i < match_length; i++) { |
|
143 |
String s = "null"; |
|
144 |
||
145 |
if(targets[i] != null) |
|
146 |
s = targets[i].getInstruction().toString(); |
|
147 |
||
17538 | 148 |
buf.append("(").append(match[i]).append(", ") |
149 |
.append(s).append(" = {").append(indices[i]).append("})"); |
|
6 | 150 |
} |
151 |
} |
|
152 |
else |
|
153 |
buf.append(" ..."); |
|
154 |
||
155 |
return buf.toString(); |
|
156 |
} |
|
157 |
||
158 |
/** |
|
159 |
* Set branch target for `i'th case |
|
160 |
*/ |
|
17538 | 161 |
public final void setTarget(int i, InstructionHandle target) { |
162 |
notifyTargetChanging(targets[i], this); |
|
6 | 163 |
targets[i] = target; |
17538 | 164 |
notifyTargetChanged(targets[i], this); |
6 | 165 |
} |
166 |
||
167 |
/** |
|
168 |
* @param old_ih old target |
|
169 |
* @param new_ih new target |
|
170 |
*/ |
|
17538 | 171 |
@Override |
6 | 172 |
public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { |
173 |
boolean targeted = false; |
|
174 |
||
175 |
if(target == old_ih) { |
|
176 |
targeted = true; |
|
177 |
setTarget(new_ih); |
|
178 |
} |
|
179 |
||
180 |
for(int i=0; i < targets.length; i++) { |
|
181 |
if(targets[i] == old_ih) { |
|
182 |
targeted = true; |
|
183 |
setTarget(i, new_ih); |
|
184 |
} |
|
185 |
} |
|
186 |
||
187 |
if(!targeted) |
|
188 |
throw new ClassGenException("Not targeting " + old_ih); |
|
189 |
} |
|
190 |
||
191 |
/** |
|
192 |
* @return true, if ih is target of this instruction |
|
193 |
*/ |
|
17538 | 194 |
@Override |
6 | 195 |
public boolean containsTarget(InstructionHandle ih) { |
196 |
if(target == ih) |
|
197 |
return true; |
|
198 |
||
199 |
for(int i=0; i < targets.length; i++) |
|
200 |
if(targets[i] == ih) |
|
201 |
return true; |
|
202 |
||
203 |
return false; |
|
204 |
} |
|
205 |
||
206 |
/** |
|
207 |
* Inform targets that they're not targeted anymore. |
|
208 |
*/ |
|
17538 | 209 |
@Override |
6 | 210 |
void dispose() { |
211 |
super.dispose(); |
|
212 |
||
213 |
for(int i=0; i < targets.length; i++) |
|
214 |
targets[i].removeTargeter(this); |
|
215 |
} |
|
216 |
||
217 |
/** |
|
218 |
* @return array of match indices |
|
219 |
*/ |
|
220 |
public int[] getMatchs() { return match; } |
|
221 |
||
222 |
/** |
|
223 |
* @return array of match target offsets |
|
224 |
*/ |
|
225 |
public int[] getIndices() { return indices; } |
|
226 |
||
227 |
/** |
|
228 |
* @return array of match targets |
|
229 |
*/ |
|
230 |
public InstructionHandle[] getTargets() { return targets; } |
|
231 |
} |