Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java
58461 views
1
/*
2
* Copyright (c) 2009, 2013, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.tools.javap;
27
28
import java.util.Arrays;
29
import java.util.HashMap;
30
import java.util.Map;
31
32
import com.sun.tools.classfile.AccessFlags;
33
import com.sun.tools.classfile.Attribute;
34
import com.sun.tools.classfile.Code_attribute;
35
import com.sun.tools.classfile.ConstantPool;
36
import com.sun.tools.classfile.ConstantPoolException;
37
import com.sun.tools.classfile.Descriptor;
38
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
39
import com.sun.tools.classfile.Instruction;
40
import com.sun.tools.classfile.Method;
41
import com.sun.tools.classfile.StackMapTable_attribute;
42
import com.sun.tools.classfile.StackMapTable_attribute.*;
43
44
import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
45
46
/**
47
* Annotate instructions with stack map.
48
*
49
* <p><b>This is NOT part of any supported API.
50
* If you write code that depends on this, you do so at your own risk.
51
* This code and its internal interfaces are subject to change or
52
* deletion without notice.</b>
53
*/
54
public class StackMapWriter extends InstructionDetailWriter {
55
static StackMapWriter instance(Context context) {
56
StackMapWriter instance = context.get(StackMapWriter.class);
57
if (instance == null)
58
instance = new StackMapWriter(context);
59
return instance;
60
}
61
62
protected StackMapWriter(Context context) {
63
super(context);
64
context.put(StackMapWriter.class, this);
65
classWriter = ClassWriter.instance(context);
66
}
67
68
public void reset(Code_attribute attr) {
69
setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable));
70
}
71
72
void setStackMap(StackMapTable_attribute attr) {
73
if (attr == null) {
74
map = null;
75
return;
76
}
77
78
Method m = classWriter.getMethod();
79
Descriptor d = m.descriptor;
80
String[] args;
81
try {
82
ConstantPool cp = classWriter.getClassFile().constant_pool;
83
String argString = d.getParameterTypes(cp);
84
args = argString.substring(1, argString.length() - 1).split("[, ]+");
85
} catch (ConstantPoolException | InvalidDescriptor e) {
86
return;
87
}
88
boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);
89
90
verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];
91
if (!isStatic)
92
initialLocals[0] = new CustomVerificationTypeInfo("this");
93
for (int i = 0; i < args.length; i++) {
94
initialLocals[(isStatic ? 0 : 1) + i] =
95
new CustomVerificationTypeInfo(args[i].replace(".", "/"));
96
}
97
98
map = new HashMap<>();
99
StackMapBuilder builder = new StackMapBuilder();
100
101
// using -1 as the pc for the initial frame effectively compensates for
102
// the difference in behavior for the first stack map frame (where the
103
// pc offset is just offset_delta) compared to subsequent frames (where
104
// the pc offset is always offset_delta+1).
105
int pc = -1;
106
107
map.put(pc, new StackMap(initialLocals, empty));
108
109
for (int i = 0; i < attr.entries.length; i++)
110
pc = attr.entries[i].accept(builder, pc);
111
}
112
113
public void writeInitialDetails() {
114
writeDetails(-1);
115
}
116
117
public void writeDetails(Instruction instr) {
118
writeDetails(instr.getPC());
119
}
120
121
private void writeDetails(int pc) {
122
if (map == null)
123
return;
124
125
StackMap m = map.get(pc);
126
if (m != null) {
127
print("StackMap locals: ", m.locals);
128
print("StackMap stack: ", m.stack);
129
}
130
131
}
132
133
void print(String label, verification_type_info[] entries) {
134
print(label);
135
for (int i = 0; i < entries.length; i++) {
136
print(" ");
137
print(entries[i]);
138
}
139
println();
140
}
141
142
void print(verification_type_info entry) {
143
if (entry == null) {
144
print("ERROR");
145
return;
146
}
147
148
switch (entry.tag) {
149
case -1:
150
print(((CustomVerificationTypeInfo) entry).text);
151
break;
152
153
case ITEM_Top:
154
print("top");
155
break;
156
157
case ITEM_Integer:
158
print("int");
159
break;
160
161
case ITEM_Float:
162
print("float");
163
break;
164
165
case ITEM_Long:
166
print("long");
167
break;
168
169
case ITEM_Double:
170
print("double");
171
break;
172
173
case ITEM_Null:
174
print("null");
175
break;
176
177
case ITEM_UninitializedThis:
178
print("uninit_this");
179
break;
180
181
case ITEM_Object:
182
try {
183
ConstantPool cp = classWriter.getClassFile().constant_pool;
184
ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);
185
print(cp.getUTF8Value(class_info.name_index));
186
} catch (ConstantPoolException e) {
187
print("??");
188
}
189
break;
190
191
case ITEM_Uninitialized:
192
print(((Uninitialized_variable_info) entry).offset);
193
break;
194
}
195
196
}
197
198
private Map<Integer, StackMap> map;
199
private ClassWriter classWriter;
200
201
class StackMapBuilder
202
implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {
203
204
public Integer visit_same_frame(same_frame frame, Integer pc) {
205
int new_pc = pc + frame.getOffsetDelta() + 1;
206
StackMap m = map.get(pc);
207
assert (m != null);
208
map.put(new_pc, m);
209
return new_pc;
210
}
211
212
public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {
213
int new_pc = pc + frame.getOffsetDelta() + 1;
214
StackMap prev = map.get(pc);
215
assert (prev != null);
216
StackMap m = new StackMap(prev.locals, frame.stack);
217
map.put(new_pc, m);
218
return new_pc;
219
}
220
221
public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {
222
int new_pc = pc + frame.getOffsetDelta() + 1;
223
StackMap prev = map.get(pc);
224
assert (prev != null);
225
StackMap m = new StackMap(prev.locals, frame.stack);
226
map.put(new_pc, m);
227
return new_pc;
228
}
229
230
public Integer visit_chop_frame(chop_frame frame, Integer pc) {
231
int new_pc = pc + frame.getOffsetDelta() + 1;
232
StackMap prev = map.get(pc);
233
assert (prev != null);
234
int k = 251 - frame.frame_type;
235
verification_type_info[] new_locals = Arrays.copyOf(prev.locals, prev.locals.length - k);
236
StackMap m = new StackMap(new_locals, empty);
237
map.put(new_pc, m);
238
return new_pc;
239
}
240
241
public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) {
242
int new_pc = pc + frame.getOffsetDelta();
243
StackMap m = map.get(pc);
244
assert (m != null);
245
map.put(new_pc, m);
246
return new_pc;
247
}
248
249
public Integer visit_append_frame(append_frame frame, Integer pc) {
250
int new_pc = pc + frame.getOffsetDelta() + 1;
251
StackMap prev = map.get(pc);
252
assert (prev != null);
253
verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length];
254
System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);
255
System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length);
256
StackMap m = new StackMap(new_locals, empty);
257
map.put(new_pc, m);
258
return new_pc;
259
}
260
261
public Integer visit_full_frame(full_frame frame, Integer pc) {
262
int new_pc = pc + frame.getOffsetDelta() + 1;
263
StackMap m = new StackMap(frame.locals, frame.stack);
264
map.put(new_pc, m);
265
return new_pc;
266
}
267
268
}
269
270
static class StackMap {
271
StackMap(verification_type_info[] locals, verification_type_info[] stack) {
272
this.locals = locals;
273
this.stack = stack;
274
}
275
276
private final verification_type_info[] locals;
277
private final verification_type_info[] stack;
278
}
279
280
static class CustomVerificationTypeInfo extends verification_type_info {
281
public CustomVerificationTypeInfo(String text) {
282
super(-1);
283
this.text = text;
284
}
285
private String text;
286
}
287
288
private final verification_type_info[] empty = { };
289
}
290
291