Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/BytecodeGenerator.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
package com.ibm.j9ddr;
23
24
import java.util.Arrays;
25
import java.util.HashMap;
26
import java.util.HashSet;
27
import java.util.Map;
28
import java.util.Set;
29
import java.util.TreeMap;
30
import java.util.regex.Pattern;
31
32
import com.ibm.j9ddr.StructureReader.ConstantDescriptor;
33
import com.ibm.j9ddr.StructureReader.FieldDescriptor;
34
import com.ibm.j9ddr.StructureReader.StructureDescriptor;
35
import com.ibm.j9ddr.tools.FlagStructureList;
36
37
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
38
import jdk.internal.org.objectweb.asm.ClassWriter;
39
import jdk.internal.org.objectweb.asm.Label;
40
import jdk.internal.org.objectweb.asm.MethodVisitor;
41
import jdk.internal.org.objectweb.asm.Opcodes;
42
import jdk.internal.org.objectweb.asm.Type;
43
44
/**
45
* Generates the class bytecodes needed by DDR to represent, as Java classes,
46
* the structures and pointers described by the blob.
47
*/
48
public class BytecodeGenerator {
49
50
private static void addFlagAlias(Map<String, String> map, String name, String alias) {
51
if (map.get(name) == null) {
52
map.put(name, alias);
53
}
54
}
55
56
private static Map<String, String> addFlagAliasesFor(Map<String, String> map, String className) {
57
/*
58
* The DDR tools from OMR, normally generate constants with names as they
59
* appear in the source code. Unfortunately, the legacy tools used in IBM
60
* builds yield different names for 'build flags'. A field override was
61
* added to provide compatibility with those legacy tools for s390
62
* J9VM_ARCH_S390=arch_s390
63
* but not for other architectures. J9ConfigFlags was introduced in an
64
* attempt to handle this difference in naming convention, but it
65
* incorrectly assumed the fields it referenced would be dynamically
66
* generated according to the blob found in the associated core file,
67
* rather than being fixed at build time. The set of aliases here replaces
68
* the ineffective mapping in J9ConfigFlags.
69
* The result is that OpenJ9 builds have additional fields in J9BuildFlags
70
* that are copied from the OMR-derived names. For example, arch_x86 is
71
* present when the legacy tools are used; when OMR tools are used, arch_x86
72
* is a copy of J9VM_ARCH_X86.
73
*
74
* Note: Do not add new aliases to this map. Instead, add overrides like
75
* was done for arch_s390 to retain compatibility with the legacy tools.
76
*/
77
if (className.equals("J9BuildFlags")) {
78
addFlagAlias(map, "arch_arm", "J9VM_ARCH_ARM");
79
addFlagAlias(map, "arch_aarch64", "J9VM_ARCH_AARCH64");
80
addFlagAlias(map, "arch_power", "J9VM_ARCH_POWER");
81
addFlagAlias(map, "arch_riscv", "J9VM_ARCH_RISCV");
82
addFlagAlias(map, "arch_x86", "J9VM_ARCH_X86");
83
}
84
return map;
85
}
86
87
static Map<String, String> getFlagAliasesFor(String className) {
88
return addFlagAliasesFor(new HashMap<String, String>(), className);
89
}
90
91
public static Map<String, String> getConstantsAndAliases(StructureDescriptor structure) {
92
Map<String, String> map = new TreeMap<>();
93
94
for (ConstantDescriptor constant : structure.getConstants()) {
95
String name = constant.getName();
96
97
map.put(name, null);
98
}
99
100
return addFlagAliasesFor(map, structure.getName());
101
}
102
103
public static byte[] getPointerClassBytes(StructureReader reader, StructureTypeManager typeManager,
104
StructureDescriptor structure, String className) {
105
if (FlagStructureList.isFlagsStructure(structure.getName())) {
106
return FlagsHelper.getClassBytes(structure, className);
107
} else {
108
return PointerHelper.getClassBytes(reader, typeManager, structure, className);
109
}
110
}
111
112
public static byte[] getStructureClassBytes(StructureDescriptor structure, String className) {
113
return StructureHelper.getClassBytes(structure, className);
114
}
115
116
}
117
118
final class FlagsHelper extends HelperBase {
119
120
public static byte[] getClassBytes(StructureDescriptor structure, String className) {
121
ClassWriter clazz = new ClassWriter(0);
122
123
clazz.visit(V1_8, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, className, null, "java/lang/Object", null);
124
125
MethodVisitor clinit = clazz.visitMethod(ACC_STATIC, "<clinit>", voidMethod, null, null);
126
127
clinit.visitCode();
128
129
Map<String, Boolean> values = new TreeMap<>();
130
131
for (ConstantDescriptor constant : structure.getConstants()) {
132
String name = constant.getName();
133
134
values.put(name, Boolean.valueOf(constant.getValue() != 0));
135
}
136
137
Map<String, String> aliases = BytecodeGenerator.getFlagAliasesFor(structure.getName());
138
139
for (Map.Entry<String, String> entry : aliases.entrySet()) {
140
String name = entry.getKey();
141
142
if (Boolean.TRUE.equals(values.get(name))) {
143
continue;
144
}
145
146
Boolean value = values.get(entry.getValue());
147
148
if (value == null) {
149
value = Boolean.FALSE;
150
}
151
152
values.put(name, value);
153
}
154
155
for (Map.Entry<String, Boolean> entry : values.entrySet()) {
156
String name = entry.getKey();
157
Boolean value = entry.getValue();
158
159
clazz.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, name, "Z", null, null).visitEnd();
160
161
clinit.visitInsn(value.booleanValue() ? ICONST_1 : ICONST_0);
162
clinit.visitFieldInsn(PUTSTATIC, className, name, Type.BOOLEAN_TYPE.getDescriptor());
163
}
164
165
clinit.visitInsn(RETURN);
166
clinit.visitMaxs(1, 0);
167
clinit.visitEnd();
168
169
MethodVisitor method = clazz.visitMethod(ACC_PRIVATE, "<init>", voidMethod, null, null);
170
171
method.visitCode();
172
method.visitVarInsn(ALOAD, 0);
173
method.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", voidMethod, false);
174
method.visitInsn(RETURN);
175
method.visitMaxs(1, 1);
176
method.visitEnd();
177
178
clazz.visitEnd();
179
180
return clazz.toByteArray();
181
}
182
183
}
184
185
abstract class HelperBase implements Opcodes {
186
187
static final String byteFromLong = Type.getMethodDescriptor(Type.BYTE_TYPE, Type.LONG_TYPE);
188
189
static final String doubleFromLong = Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.LONG_TYPE);
190
191
static final String doubleFromVoid = Type.getMethodDescriptor(Type.DOUBLE_TYPE);
192
193
static final String floatFromLong = Type.getMethodDescriptor(Type.FLOAT_TYPE, Type.LONG_TYPE);
194
195
static final String floatFromVoid = Type.getMethodDescriptor(Type.FLOAT_TYPE);
196
197
static final String intFromLong = Type.getMethodDescriptor(Type.INT_TYPE, Type.LONG_TYPE);
198
199
static final String longFromLong = Type.getMethodDescriptor(Type.LONG_TYPE, Type.LONG_TYPE);
200
201
static final String longFromVoid = Type.getMethodDescriptor(Type.LONG_TYPE);
202
203
static final String shortFromLong = Type.getMethodDescriptor(Type.SHORT_TYPE, Type.LONG_TYPE);
204
205
static final String voidFromLong = Type.getMethodDescriptor(Type.VOID_TYPE, Type.LONG_TYPE);
206
207
static final String voidMethod = Type.getMethodDescriptor(Type.VOID_TYPE);
208
209
static final void addLong(MethodVisitor method, long value) {
210
if (value != 0) {
211
loadLong(method, value);
212
method.visitInsn(LADD);
213
}
214
}
215
216
static final void loadInt(MethodVisitor method, int value) {
217
switch (value) {
218
case -1:
219
method.visitInsn(ICONST_M1);
220
break;
221
case 0:
222
method.visitInsn(ICONST_0);
223
break;
224
case 1:
225
method.visitInsn(ICONST_1);
226
break;
227
case 2:
228
method.visitInsn(ICONST_2);
229
break;
230
case 3:
231
method.visitInsn(ICONST_3);
232
break;
233
case 4:
234
method.visitInsn(ICONST_4);
235
break;
236
case 5:
237
method.visitInsn(ICONST_5);
238
break;
239
default:
240
method.visitLdcInsn(Integer.valueOf(value));
241
break;
242
}
243
}
244
245
static final void loadLong(MethodVisitor method, long value) {
246
if (value == 0) {
247
method.visitInsn(LCONST_0);
248
} else if (value == 1) {
249
method.visitInsn(LCONST_1);
250
} else {
251
method.visitLdcInsn(Long.valueOf(value));
252
}
253
}
254
255
}
256
257
final class PointerHelper extends HelperBase {
258
259
private static final Pattern ConstPattern = Pattern.compile("\\s*\\bconst\\s+");
260
261
private static final Set<String> predefinedDataTypes;
262
263
private static final Set<String> predefinedPointerTypes;
264
265
private static final Pattern TypeTagPattern = Pattern.compile("\\s*\\b(class|enum|struct)\\s+");
266
267
static {
268
Set<String> common = addNames(new HashSet<String>(), "I8 U8 I16 U16 I32 U32 I64 U64 IDATA UDATA Void");
269
270
predefinedDataTypes = new HashSet<String>(common);
271
addNames(predefinedDataTypes, "Scalar IScalar UScalar");
272
273
predefinedPointerTypes = new HashSet<String>(common);
274
addNames(predefinedPointerTypes, "Abstract Bool Double Enum Float ObjectClassReference ObjectMonitorReference");
275
addNames(predefinedPointerTypes, "ObjectReference Pointer SelfRelative Structure WideSelfRelative");
276
}
277
278
private static Set<String> addNames(Set<String> set, String names) {
279
set.addAll(Arrays.asList(names.split(" ")));
280
return set;
281
}
282
283
private static boolean checkPresent(FieldDescriptor field, MethodVisitor method) {
284
if (field.isPresent()) {
285
return true;
286
}
287
288
String noSuchField = "java/lang/NoSuchFieldException";
289
290
method.visitTypeInsn(NEW, noSuchField);
291
method.visitInsn(DUP);
292
method.visitMethodInsn(INVOKESPECIAL, noSuchField, "<init>", voidMethod, false);
293
294
method.visitInsn(ATHROW);
295
296
return false;
297
}
298
299
/*
300
* The new DDR tooling doesn't always distinguish between IDATA and I32 or I64
301
* or between UDATA and U32 or U64. Thus the return types of accessor methods
302
* must be more general to be compatible with the pointer types derived from
303
* both 32-bit and 64-bit core files. This generalization must occur even for
304
* the pointer stubs generated from this code so that incompatibilities will
305
* be discovered at build time, rather than at run time.
306
*/
307
private static String generalizeSimpleType(String type) {
308
if ("I32".equals(type) || "I64".equals(type)) {
309
return "IDATA";
310
} else if ("U32".equals(type) || "U64".equals(type)) {
311
return "UDATA";
312
} else {
313
return type;
314
}
315
}
316
317
static byte[] getClassBytes(StructureReader reader, StructureTypeManager typeManager, StructureDescriptor structure,
318
String className) {
319
PointerHelper helper = new PointerHelper(reader, typeManager, structure, className);
320
321
return helper.generate();
322
}
323
324
private static String getEnumType(String enumType) {
325
int start = enumType.startsWith("enum ") ? 5 : 0;
326
int end = enumType.length();
327
328
if (enumType.endsWith("[]")) {
329
end -= 2;
330
}
331
332
return enumType.substring(start, end);
333
}
334
335
private static String getTargetType(String pointerType) {
336
String type = ConstPattern.matcher(pointerType).replaceAll("").trim();
337
int firstStar = type.indexOf('*');
338
339
if (type.indexOf('*', firstStar + 1) > 0) {
340
// two or more levels of indirection
341
return "Pointer";
342
}
343
344
type = type.substring(0, firstStar).trim();
345
346
if (type.equals("bool")) {
347
return "Bool";
348
} else if (type.equals("double")) {
349
return "Double";
350
} else if (type.equals("float")) {
351
return "Float";
352
} else if (type.equals("void")) {
353
return "Void";
354
} else {
355
return type;
356
}
357
}
358
359
private static String removeTypeTags(String type) {
360
return TypeTagPattern.matcher(type).replaceAll("").trim();
361
}
362
363
private final Type abstractPointerType;
364
365
private final String basePrefix;
366
367
private final String className;
368
369
private final Type classType;
370
371
private final ClassWriter clazz;
372
373
private final String[] normalThrows;
374
375
private final String[] optionalThrows;
376
377
private final StructureReader reader;
378
379
private final Type scalarType;
380
381
private final StructureDescriptor structure;
382
383
private final StructureTypeManager typeManager;
384
385
private final Type udataType;
386
387
private PointerHelper(StructureReader reader, StructureTypeManager typeManager, StructureDescriptor structure,
388
String className) {
389
super();
390
391
int index = className.indexOf("/pointer/generated/");
392
393
if (index <= 0) {
394
throw new IllegalArgumentException(className);
395
}
396
397
String prefix = className.substring(0, index + 1); // ends with '/vmNN/'
398
399
this.abstractPointerType = Type.getObjectType(prefix + "pointer/AbstractPointer");
400
this.basePrefix = prefix;
401
this.className = className;
402
this.classType = Type.getObjectType(className);
403
this.clazz = new ClassWriter(0);
404
this.normalThrows = new String[] { "com/ibm/j9ddr/CorruptDataException" };
405
this.optionalThrows = new String[] { "com/ibm/j9ddr/CorruptDataException", "java/lang/NoSuchFieldException" };
406
this.reader = reader;
407
this.scalarType = Type.getObjectType(prefix + "types/Scalar");
408
this.structure = structure;
409
this.typeManager = typeManager;
410
this.udataType = Type.getObjectType(prefix + "types/UDATA");
411
}
412
413
private MethodVisitor beginAnnotatedMethod(FieldDescriptor field, String name, String descriptor) {
414
MethodVisitor method = beginMethod(field, name, descriptor);
415
416
if (field.isPresent()) {
417
Type annotationType = Type.getObjectType("com/ibm/j9ddr/GeneratedFieldAccessor");
418
AnnotationVisitor annotation = method.visitAnnotation(annotationType.getDescriptor(), true);
419
420
annotation.visit("offsetFieldName", String.format("_%sOffset_", field.getName()));
421
annotation.visit("declaredType", field.getDeclaredType());
422
annotation.visitEnd();
423
}
424
425
return method;
426
}
427
428
private MethodVisitor beginMethod(FieldDescriptor field, String name, String descriptor) {
429
String[] exceptions = field.isOptional() ? optionalThrows : normalThrows;
430
431
return clazz.visitMethod(ACC_PUBLIC, name, descriptor, null, exceptions);
432
}
433
434
private void doAccessorMethods() {
435
for (FieldDescriptor field : structure.getFields()) {
436
String fieldName = field.getName();
437
438
if (fieldName.isEmpty() || fieldName.indexOf('#') >= 0) {
439
// Omit anonymous fields (xlc generates names containing '#').
440
continue;
441
}
442
443
String typeName = field.getType();
444
int type = typeManager.getType(typeName);
445
446
switch (type) {
447
case StructureTypeManager.TYPE_STRUCTURE:
448
doStructureMethod(field);
449
break;
450
case StructureTypeManager.TYPE_STRUCTURE_POINTER:
451
doStructurePointerMethod(field);
452
break;
453
case StructureTypeManager.TYPE_POINTER:
454
doPointerMethod(field);
455
break;
456
case StructureTypeManager.TYPE_ARRAY:
457
doArrayMethod(field);
458
break;
459
case StructureTypeManager.TYPE_J9SRP:
460
doSRPMethod(field, false);
461
break;
462
case StructureTypeManager.TYPE_J9WSRP:
463
doSRPMethod(field, true);
464
break;
465
case StructureTypeManager.TYPE_J9SRP_POINTER:
466
doSRPPointerMethod(field, false);
467
break;
468
case StructureTypeManager.TYPE_J9WSRP_POINTER:
469
doSRPPointerMethod(field, true);
470
break;
471
case StructureTypeManager.TYPE_FJ9OBJECT:
472
doFJ9ObjectMethod(field);
473
break;
474
case StructureTypeManager.TYPE_FJ9OBJECT_POINTER:
475
doFJ9ObjectPointerMethod(field);
476
break;
477
case StructureTypeManager.TYPE_J9OBJECTCLASS:
478
doJ9ObjectClassMethod(field);
479
break;
480
case StructureTypeManager.TYPE_J9OBJECTCLASS_POINTER:
481
doJ9ObjectClassPointerMethod(field);
482
break;
483
case StructureTypeManager.TYPE_J9OBJECTMONITOR:
484
doJ9ObjectMonitorMethod(field);
485
break;
486
case StructureTypeManager.TYPE_J9OBJECTMONITOR_POINTER:
487
doJ9ObjectMonitorPointerMethod(field);
488
break;
489
case StructureTypeManager.TYPE_VOID:
490
doStructureMethod(field);
491
break;
492
case StructureTypeManager.TYPE_BOOL:
493
doBooleanMethod(field);
494
break;
495
case StructureTypeManager.TYPE_DOUBLE:
496
doDoubleMethod(field);
497
break;
498
case StructureTypeManager.TYPE_FLOAT:
499
doFloatMethod(field);
500
break;
501
case StructureTypeManager.TYPE_ENUM:
502
doEnumMethod(field);
503
break;
504
case StructureTypeManager.TYPE_ENUM_POINTER:
505
doEnumPointerMethod(field);
506
break;
507
case StructureTypeManager.TYPE_BITFIELD:
508
int colonIndex = typeName.indexOf(':');
509
if (colonIndex <= 0) {
510
throw new IllegalArgumentException(String.format("%s.%s : %s is not a valid bitfield",
511
structure.getName(), fieldName, typeName));
512
}
513
String baseType = typeName.substring(0, colonIndex);
514
int width = Integer.parseInt(typeName.substring(colonIndex + 1));
515
doBitfieldMethod(field, baseType, width);
516
break;
517
518
default:
519
if ((StructureTypeManager.TYPE_SIMPLE_MIN <= type) && (type <= StructureTypeManager.TYPE_SIMPLE_MAX)) {
520
doSimpleTypeMethod(field, type);
521
} else {
522
// omit unhandled field type
523
}
524
break;
525
}
526
}
527
}
528
529
/* Sample generated code:
530
*
531
* public ObjectMonitorReferencePointer objectMonitorLookupCacheEA() throws CorruptDataException {
532
* return ObjectMonitorReferencePointer.cast(nonNullFieldEA(J9VMThread._objectMonitorLookupCacheOffset_));
533
* }
534
*/
535
private void doArrayMethod(FieldDescriptor field) {
536
String fieldType = field.getType();
537
String componentType = fieldType.substring(0, fieldType.lastIndexOf('[')).trim();
538
int type = typeManager.getType(componentType);
539
540
switch (type) {
541
case StructureTypeManager.TYPE_BOOL:
542
doEAMethod("Bool", field);
543
return;
544
case StructureTypeManager.TYPE_DOUBLE:
545
doEAMethod("Double", field);
546
return;
547
case StructureTypeManager.TYPE_ENUM:
548
doEnumEAMethod(field);
549
return;
550
case StructureTypeManager.TYPE_FLOAT:
551
doEAMethod("Float", field);
552
return;
553
case StructureTypeManager.TYPE_FJ9OBJECT:
554
doEAMethod("ObjectReference", field);
555
return;
556
case StructureTypeManager.TYPE_J9OBJECTCLASS:
557
doEAMethod("ObjectClassReference", field);
558
return;
559
case StructureTypeManager.TYPE_J9OBJECTMONITOR:
560
doEAMethod("ObjectMonitorReference", field);
561
return;
562
case StructureTypeManager.TYPE_STRUCTURE:
563
doEAMethod(removeTypeTags(componentType), field);
564
return;
565
case StructureTypeManager.TYPE_ARRAY:
566
case StructureTypeManager.TYPE_FJ9OBJECT_POINTER:
567
case StructureTypeManager.TYPE_J9OBJECTCLASS_POINTER:
568
case StructureTypeManager.TYPE_J9OBJECTMONITOR_POINTER:
569
case StructureTypeManager.TYPE_POINTER:
570
case StructureTypeManager.TYPE_STRUCTURE_POINTER:
571
// All these pointer types look the same.
572
doEAMethod("Pointer", field);
573
return;
574
default:
575
if ((StructureTypeManager.TYPE_SIMPLE_MIN <= type) && (type <= StructureTypeManager.TYPE_SIMPLE_MAX)) {
576
doEAMethod(componentType, field);
577
return;
578
}
579
break;
580
case StructureTypeManager.TYPE_BITFIELD: // Is a bitfield array even legal?
581
case StructureTypeManager.TYPE_J9SRP: // not implemented
582
case StructureTypeManager.TYPE_J9WSRP: // not implemented
583
break;
584
}
585
586
throw new IllegalArgumentException("Unrecognized array: " + fieldType);
587
}
588
589
/* Sample generated code:
590
*
591
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_isDirOffset_", declaredType="uint32_t:1")
592
* public UDATA isDir() throws CorruptDataException {
593
* return getU32Bitfield(J9FileStat._isDir_s_, J9FileStat._isDir_b_);
594
* }
595
*/
596
private void doBitfieldMethod(FieldDescriptor field, String baseType, int width) {
597
String fieldName = field.getName();
598
Type qualifiedBaseType = Type.getObjectType(qualifyType(baseType));
599
Type qualifiedReturnType = Type.getObjectType(qualifyType(generalizeSimpleType(baseType)));
600
String returnDesc = Type.getMethodDescriptor(qualifiedReturnType);
601
String startFieldName = String.format("_%s_s_", fieldName);
602
String accessorName = String.format("get%sBitfield", baseType);
603
String accessorDesc = Type.getMethodDescriptor(qualifiedBaseType, Type.INT_TYPE, Type.INT_TYPE);
604
605
MethodVisitor method = beginAnnotatedMethod(field, fieldName, returnDesc);
606
607
method.visitCode();
608
if (checkPresent(field, method)) {
609
method.visitVarInsn(ALOAD, 0);
610
method.visitFieldInsn(GETSTATIC, getStructureClassName(), startFieldName, Type.INT_TYPE.getDescriptor());
611
loadInt(method, width);
612
method.visitMethodInsn(INVOKEVIRTUAL, className, accessorName, accessorDesc, false);
613
method.visitInsn(ARETURN);
614
}
615
method.visitMaxs(3, 1);
616
method.visitEnd();
617
618
// no EA method for a bitfield
619
}
620
621
/* Sample generated code:
622
*
623
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="__isAnonOffset_", declaredType="bool")
624
* public boolean _isAnon() throws CorruptDataException {
625
* return getBoolAtOffset(ClassFileWriter.__isAnonOffset_);
626
* }
627
*/
628
private void doBooleanMethod(FieldDescriptor field) {
629
String returnDesc = Type.getMethodDescriptor(Type.BOOLEAN_TYPE);
630
String accessorDesc = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.LONG_TYPE);
631
632
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
633
634
method.visitCode();
635
if (checkPresent(field, method)) {
636
method.visitVarInsn(ALOAD, 0);
637
loadLong(method, field.getOffset());
638
method.visitMethodInsn(INVOKEVIRTUAL, className, "getBoolAtOffset", accessorDesc, false);
639
method.visitInsn(IRETURN);
640
}
641
method.visitMaxs(3, 1);
642
method.visitEnd();
643
644
doEAMethod("Bool", field);
645
}
646
647
private void doClassAnnotation() {
648
// @com.ibm.j9ddr.GeneratedPointerClass(structureClass=BASE.class)
649
Type annotationType = Type.getObjectType("com/ibm/j9ddr/GeneratedPointerClass");
650
AnnotationVisitor annotation = clazz.visitAnnotation(annotationType.getDescriptor(), true);
651
Type structureType = Type.getObjectType(getStructureClassName());
652
653
annotation.visit("structureClass", structureType);
654
annotation.visitEnd();
655
}
656
657
private void doConstructors(String superClassName) {
658
final String abstractPointerFromLong = Type.getMethodDescriptor(abstractPointerType, Type.LONG_TYPE);
659
final String abstractPointerFromScalar = Type.getMethodDescriptor(abstractPointerType, scalarType);
660
final String classFromLong = Type.getMethodDescriptor(classType, Type.LONG_TYPE);
661
final String classFromScalar = Type.getMethodDescriptor(classType, scalarType);
662
MethodVisitor method;
663
664
// protected SELF(long address) { super(address); }
665
{
666
method = clazz.visitMethod(ACC_PROTECTED, "<init>", voidFromLong, null, null);
667
668
method.visitCode();
669
method.visitVarInsn(ALOAD, 0);
670
method.visitVarInsn(LLOAD, 1);
671
method.visitMethodInsn(INVOKESPECIAL, superClassName, "<init>", voidFromLong, false);
672
method.visitInsn(RETURN);
673
method.visitMaxs(3, 3);
674
method.visitEnd();
675
}
676
677
// public static SELF cast(long address) { if (address == 0) return NULL; return new SELF(address); }
678
{
679
method = clazz.visitMethod(ACC_PUBLIC | ACC_STATIC, "cast", classFromLong, null, null);
680
681
Label nonNull = new Label();
682
683
method.visitCode();
684
method.visitVarInsn(LLOAD, 0);
685
method.visitInsn(LCONST_0);
686
method.visitInsn(LCMP);
687
method.visitJumpInsn(IFNE, nonNull);
688
method.visitFieldInsn(GETSTATIC, className, "NULL", classType.getDescriptor());
689
method.visitInsn(ARETURN);
690
691
method.visitLabel(nonNull);
692
method.visitFrame(F_SAME, 0, null, 0, null);
693
method.visitTypeInsn(NEW, className);
694
method.visitInsn(DUP);
695
method.visitVarInsn(LLOAD, 0);
696
method.visitMethodInsn(INVOKESPECIAL, className, "<init>", voidFromLong, false);
697
method.visitInsn(ARETURN);
698
699
method.visitMaxs(4, 2);
700
method.visitEnd();
701
}
702
703
// public static SELF cast(AbstractPointer structure) { return cast(structure.getAddress()); }
704
{
705
method = clazz.visitMethod(ACC_PUBLIC | ACC_STATIC, "cast",
706
Type.getMethodDescriptor(classType, abstractPointerType), null, null);
707
708
method.visitCode();
709
method.visitVarInsn(ALOAD, 0);
710
method.visitMethodInsn(INVOKEVIRTUAL, abstractPointerType.getInternalName(), "getAddress", longFromVoid,
711
false);
712
method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);
713
method.visitInsn(ARETURN);
714
method.visitMaxs(2, 1);
715
method.visitEnd();
716
}
717
718
// public static SELF cast(UDATA udata) { return cast(udata.longValue()); }
719
{
720
method = clazz.visitMethod(ACC_PUBLIC | ACC_STATIC, "cast", Type.getMethodDescriptor(classType, udataType),
721
null, null);
722
723
method.visitCode();
724
method.visitVarInsn(ALOAD, 0);
725
method.visitMethodInsn(INVOKEVIRTUAL, udataType.getInternalName(), "longValue", longFromVoid, false);
726
method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);
727
method.visitInsn(ARETURN);
728
method.visitMaxs(2, 1);
729
method.visitEnd();
730
}
731
732
// public SELF add(long count) { return addOffset(count * BASE.SIZEOF); }
733
{
734
method = clazz.visitMethod(ACC_PUBLIC, "add", classFromLong, null, null);
735
736
method.visitCode();
737
method.visitVarInsn(ALOAD, 0);
738
method.visitVarInsn(LLOAD, 1);
739
loadLong(method, structure.getSizeOf());
740
method.visitInsn(LMUL);
741
method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromLong, false);
742
method.visitInsn(ARETURN);
743
method.visitMaxs(5, 3);
744
method.visitEnd();
745
746
// bridge: AbstractPointer add(long count)
747
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "add", abstractPointerFromLong, null, null);
748
749
method.visitCode();
750
method.visitVarInsn(ALOAD, 0);
751
method.visitVarInsn(LLOAD, 1);
752
method.visitMethodInsn(INVOKEVIRTUAL, className, "add", classFromLong, false);
753
method.visitInsn(ARETURN);
754
method.visitMaxs(3, 3);
755
method.visitEnd();
756
}
757
758
// public SELF add(Scalar count) { return add(count.longValue()); }
759
{
760
method = clazz.visitMethod(ACC_PUBLIC, "add", classFromScalar, null, null);
761
762
method.visitCode();
763
method.visitVarInsn(ALOAD, 0);
764
method.visitVarInsn(ALOAD, 1);
765
method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);
766
method.visitMethodInsn(INVOKEVIRTUAL, className, "add", classFromLong, false);
767
method.visitInsn(ARETURN);
768
method.visitMaxs(3, 2);
769
method.visitEnd();
770
771
// bridge: AbstractPointer add(Scalar count)
772
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "add", abstractPointerFromScalar, null, null);
773
774
method.visitCode();
775
method.visitVarInsn(ALOAD, 0);
776
method.visitVarInsn(ALOAD, 1);
777
method.visitMethodInsn(INVOKEVIRTUAL, className, "add", classFromScalar, false);
778
method.visitInsn(ARETURN);
779
method.visitMaxs(2, 2);
780
method.visitEnd();
781
}
782
783
// public SELF addOffset(long offset) { return cast(address + offset); }
784
{
785
method = clazz.visitMethod(ACC_PUBLIC, "addOffset", classFromLong, null, null);
786
787
method.visitCode();
788
method.visitVarInsn(ALOAD, 0);
789
method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());
790
method.visitVarInsn(LLOAD, 1);
791
method.visitInsn(LADD);
792
method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);
793
method.visitInsn(ARETURN);
794
method.visitMaxs(4, 3);
795
method.visitEnd();
796
797
// bridge: AbstractPointer addOffset(long offset)
798
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "addOffset", abstractPointerFromLong, null, null);
799
800
method.visitCode();
801
method.visitVarInsn(ALOAD, 0);
802
method.visitVarInsn(LLOAD, 1);
803
method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromLong, false);
804
method.visitInsn(ARETURN);
805
method.visitMaxs(3, 3);
806
method.visitEnd();
807
}
808
809
// public SELF addOffset(Scalar offset) { return addOffset(offset.longValue()); }
810
{
811
method = clazz.visitMethod(ACC_PUBLIC, "addOffset", classFromScalar, null, null);
812
813
method.visitCode();
814
method.visitVarInsn(ALOAD, 0);
815
method.visitVarInsn(ALOAD, 1);
816
method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);
817
method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromLong, false);
818
method.visitInsn(ARETURN);
819
method.visitMaxs(3, 2);
820
method.visitEnd();
821
822
// bridge: AbstractPointer addOffset(Scalar offset)
823
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "addOffset", abstractPointerFromScalar, null, null);
824
825
method.visitCode();
826
method.visitVarInsn(ALOAD, 0);
827
method.visitVarInsn(ALOAD, 1);
828
method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromScalar, false);
829
method.visitInsn(ARETURN);
830
method.visitMaxs(2, 2);
831
method.visitEnd();
832
}
833
834
// public SELF sub(long count) { return subOffset(count * SIZEOF); }
835
{
836
method = clazz.visitMethod(ACC_PUBLIC, "sub", classFromLong, null, null);
837
838
method.visitCode();
839
method.visitVarInsn(ALOAD, 0);
840
method.visitVarInsn(LLOAD, 1);
841
loadLong(method, structure.getSizeOf());
842
method.visitInsn(LMUL);
843
method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromLong, false);
844
method.visitInsn(ARETURN);
845
method.visitMaxs(5, 3);
846
method.visitEnd();
847
848
// bridge: AbstractPointer sub(long count)
849
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "sub", abstractPointerFromLong, null, null);
850
851
method.visitCode();
852
method.visitVarInsn(ALOAD, 0);
853
method.visitVarInsn(LLOAD, 1);
854
method.visitMethodInsn(INVOKEVIRTUAL, className, "sub", classFromLong, false);
855
method.visitInsn(ARETURN);
856
method.visitMaxs(3, 3);
857
method.visitEnd();
858
}
859
860
// public SELF sub(Scalar count) { return sub(count.longValue()); }
861
{
862
method = clazz.visitMethod(ACC_PUBLIC, "sub", classFromScalar, null, null);
863
864
method.visitCode();
865
method.visitVarInsn(ALOAD, 0);
866
method.visitVarInsn(ALOAD, 1);
867
method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);
868
method.visitMethodInsn(INVOKEVIRTUAL, className, "sub", classFromLong, false);
869
method.visitInsn(ARETURN);
870
method.visitMaxs(3, 2);
871
method.visitEnd();
872
873
// bridge: AbstractPointer sub(Scalar count)
874
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "sub", abstractPointerFromScalar, null, null);
875
876
method.visitCode();
877
method.visitVarInsn(ALOAD, 0);
878
method.visitVarInsn(ALOAD, 1);
879
method.visitMethodInsn(INVOKEVIRTUAL, className, "sub", classFromScalar, false);
880
method.visitInsn(ARETURN);
881
method.visitMaxs(2, 2);
882
method.visitEnd();
883
}
884
885
// public SELF subOffset(long offset) { return cast(address - offset); }
886
{
887
method = clazz.visitMethod(ACC_PUBLIC, "subOffset", classFromLong, null, null);
888
889
method.visitCode();
890
method.visitVarInsn(ALOAD, 0);
891
method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());
892
method.visitVarInsn(LLOAD, 1);
893
method.visitInsn(LSUB);
894
method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);
895
method.visitInsn(ARETURN);
896
method.visitMaxs(5, 3);
897
method.visitEnd();
898
899
// bridge: AbstractPointer subOffset(long offset)
900
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "subOffset", abstractPointerFromLong, null, null);
901
902
method.visitCode();
903
method.visitVarInsn(ALOAD, 0);
904
method.visitVarInsn(LLOAD, 1);
905
method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromLong, false);
906
method.visitInsn(ARETURN);
907
method.visitMaxs(3, 3);
908
method.visitEnd();
909
}
910
911
// public SELF subOffset(Scalar offset) { return subOffset(offset.longValue()); }
912
{
913
method = clazz.visitMethod(ACC_PUBLIC, "subOffset", classFromScalar, null, null);
914
915
method.visitCode();
916
method.visitVarInsn(ALOAD, 0);
917
method.visitVarInsn(ALOAD, 1);
918
method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);
919
method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromLong, false);
920
method.visitInsn(ARETURN);
921
method.visitMaxs(3, 2);
922
method.visitEnd();
923
924
// bridge: AbstractPointer subOffset(Scalar offset)
925
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "subOffset", abstractPointerFromScalar, null, null);
926
927
method.visitCode();
928
method.visitVarInsn(ALOAD, 0);
929
method.visitVarInsn(ALOAD, 1);
930
method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromScalar, false);
931
method.visitInsn(ARETURN);
932
method.visitMaxs(2, 2);
933
method.visitEnd();
934
}
935
936
// public SELF untag(long mask) { return cast(address & ~mask); }
937
{
938
method = clazz.visitMethod(ACC_PUBLIC, "untag", classFromLong, null, null);
939
940
method.visitCode();
941
method.visitVarInsn(ALOAD, 0);
942
method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());
943
method.visitVarInsn(LLOAD, 1);
944
loadLong(method, -1);
945
method.visitInsn(LXOR);
946
method.visitInsn(LAND);
947
948
method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);
949
method.visitInsn(ARETURN);
950
method.visitMaxs(6, 3);
951
method.visitEnd();
952
953
// bridge: AbstractPointer untag(long tagBits)
954
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "untag", abstractPointerFromLong, null, null);
955
956
method.visitCode();
957
method.visitVarInsn(ALOAD, 0);
958
method.visitVarInsn(LLOAD, 1);
959
method.visitMethodInsn(INVOKEVIRTUAL, className, "untag", classFromLong, false);
960
method.visitInsn(ARETURN);
961
method.visitMaxs(3, 3);
962
method.visitEnd();
963
}
964
965
// public SELF untag() { return untag(UDATA.SIZEOF - 1); }
966
{
967
String classFromVoid = Type.getMethodDescriptor(classType);
968
969
method = clazz.visitMethod(ACC_PUBLIC, "untag", classFromVoid, null, null);
970
971
method.visitCode();
972
method.visitVarInsn(ALOAD, 0);
973
loadLong(method, reader.getSizeOfUDATA() - 1);
974
method.visitMethodInsn(INVOKEVIRTUAL, className, "untag", classFromLong, false);
975
method.visitInsn(ARETURN);
976
method.visitMaxs(3, 1);
977
method.visitEnd();
978
979
// bridge: AbstractPointer untag()
980
method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "untag", Type.getMethodDescriptor(abstractPointerType), null, null);
981
982
method.visitCode();
983
method.visitVarInsn(ALOAD, 0);
984
method.visitMethodInsn(INVOKEVIRTUAL, className, "untag", classFromVoid, false);
985
method.visitInsn(ARETURN);
986
method.visitMaxs(1, 1);
987
method.visitEnd();
988
}
989
990
// protected long sizeOfBaseType() { return BASE.SIZEOF; }
991
{
992
method = clazz.visitMethod(ACC_PROTECTED, "sizeOfBaseType", longFromVoid, null, null);
993
994
method.visitCode();
995
loadLong(method, structure.getSizeOf());
996
method.visitInsn(LRETURN);
997
method.visitMaxs(2, 1);
998
method.visitEnd();
999
}
1000
}
1001
1002
/* Sample generated code:
1003
*
1004
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_fifteenMinuteAverageOffset_", declaredType="double")
1005
* public double fifteenMinuteAverage() throws CorruptDataException {
1006
* return getDoubleAtOffset(J9PortSysInfoLoadData._fifteenMinuteAverageOffset_);
1007
* }
1008
*/
1009
private void doDoubleMethod(FieldDescriptor field) {
1010
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), doubleFromVoid);
1011
1012
method.visitCode();
1013
if (checkPresent(field, method)) {
1014
method.visitVarInsn(ALOAD, 0);
1015
loadLong(method, field.getOffset());
1016
method.visitMethodInsn(INVOKEVIRTUAL, className, "getDoubleAtOffset", doubleFromLong, false);
1017
method.visitInsn(DRETURN);
1018
}
1019
method.visitMaxs(3, 1);
1020
method.visitEnd();
1021
1022
doEAMethod("Double", field);
1023
}
1024
1025
/* Sample generated code:
1026
*
1027
* public UDATAPointer castClassCacheEA() throws CorruptDataException {
1028
* return UDATAPointer.cast(nonNullFieldEA(J9Class._castClassCacheOffset_));
1029
* }
1030
*/
1031
private void doEAMethod(String actualType, FieldDescriptor field) {
1032
String accessorName = field.getName() + "EA";
1033
String returnType = generalizeSimpleType(actualType);
1034
String qualifiedReturnType = qualifyPointerType(returnType);
1035
String qualifiedActualType = qualifyPointerType(actualType);
1036
1037
String returnDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedReturnType));
1038
String actualDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedActualType), Type.LONG_TYPE);
1039
1040
MethodVisitor method = beginMethod(field, accessorName, returnDesc);
1041
1042
method.visitCode();
1043
if (checkPresent(field, method)) {
1044
method.visitVarInsn(ALOAD, 0);
1045
loadLong(method, field.getOffset());
1046
method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);
1047
method.visitMethodInsn(INVOKESTATIC, qualifiedActualType, "cast", actualDesc, false);
1048
method.visitInsn(ARETURN);
1049
}
1050
method.visitMaxs(3, 1);
1051
method.visitEnd();
1052
}
1053
1054
/* Sample generated code:
1055
*
1056
* public EnumPointer _buildResultEA() throws CorruptDataException {
1057
* return EnumPointer.cast(nonNullFieldEA(ClassFileWriter.__buildResultOffset_, BuildResult.class));
1058
* }
1059
*/
1060
private void doEnumEAMethod(FieldDescriptor field) {
1061
String accessorName = field.getName() + "EA";
1062
String enumPointerDesc = qualifyPointerType("Enum");
1063
Type enumPointerType = Type.getObjectType(enumPointerDesc);
1064
String returnDesc = Type.getMethodDescriptor(enumPointerType);
1065
String castDesc = Type.getMethodDescriptor(enumPointerType, Type.LONG_TYPE, Type.getType(Class.class));
1066
Type enumType = Type.getObjectType(qualifyType(getEnumType(field.getType())));
1067
1068
MethodVisitor method = beginMethod(field, accessorName, returnDesc);
1069
1070
method.visitCode();
1071
if (checkPresent(field, method)) {
1072
method.visitVarInsn(ALOAD, 0);
1073
loadLong(method, field.getOffset());
1074
method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);
1075
method.visitLdcInsn(enumType);
1076
method.visitMethodInsn(INVOKESTATIC, enumPointerDesc, "cast", castDesc, false);
1077
method.visitInsn(ARETURN);
1078
}
1079
method.visitMaxs(3, 1);
1080
method.visitEnd();
1081
}
1082
1083
/* Sample generated code:
1084
*
1085
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_physicalProcessorOffset_", declaredType="J9ProcessorArchitecture")
1086
* public long physicalProcessor() throws CorruptDataException {
1087
* return getIntAtOffset(J9ProcessorDesc._physicalProcessorOffset_);
1088
* }
1089
*
1090
* If the size of the field type is not 4, getByteAtOffset, getShortAtOffset
1091
* or getLongAtOffset is used as appropriate.
1092
*/
1093
private void doEnumMethod(FieldDescriptor field) {
1094
String enumType = getEnumType(field.getType());
1095
int enumSize = reader.getStructureSizeOf(enumType);
1096
PrimitiveAccessor accessor = PrimitiveAccessor.forSize(enumSize);
1097
1098
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), longFromVoid);
1099
1100
method.visitCode();
1101
if (checkPresent(field, method)) {
1102
method.visitVarInsn(ALOAD, 0);
1103
loadLong(method, field.getOffset());
1104
method.visitMethodInsn(INVOKEVIRTUAL, className, accessor.methodName, accessor.descriptor, false);
1105
if (!accessor.returnsLong) {
1106
method.visitInsn(I2L);
1107
}
1108
method.visitInsn(LRETURN);
1109
}
1110
method.visitMaxs(3, 1);
1111
method.visitEnd();
1112
1113
doEnumEAMethod(field);
1114
}
1115
1116
/* Sample generated code:
1117
*
1118
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="__resultOffset_", declaredType="BuildResult*")
1119
* public EnumPointer _result() throws CorruptDataException {
1120
* return EnumPointer.cast(getPointerAtOffset(ROMClassVerbosePhase.__resultOffset_), BuildResult.class);
1121
* }
1122
*/
1123
private void doEnumPointerMethod(FieldDescriptor field) {
1124
String enumPointerDesc = qualifyPointerType("Enum");
1125
Type enumPointerType = Type.getObjectType(enumPointerDesc);
1126
String returnDesc = Type.getMethodDescriptor(enumPointerType);
1127
String castDesc = Type.getMethodDescriptor(enumPointerType, Type.LONG_TYPE, Type.getType(Class.class));
1128
String targetType = getTargetType(getEnumType(field.getType()));
1129
Type enumType = Type.getObjectType(qualifyType(targetType));
1130
1131
MethodVisitor method = beginMethod(field, field.getName(), returnDesc);
1132
1133
method.visitCode();
1134
if (checkPresent(field, method)) {
1135
method.visitVarInsn(ALOAD, 0);
1136
loadLong(method, field.getOffset());
1137
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1138
method.visitLdcInsn(enumType);
1139
method.visitMethodInsn(INVOKESTATIC, enumPointerDesc, "cast", castDesc, false);
1140
method.visitInsn(ARETURN);
1141
}
1142
method.visitMaxs(3, 2);
1143
method.visitEnd();
1144
1145
doEAMethod("Pointer", field);
1146
}
1147
1148
/* Sample generated code:
1149
*
1150
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_refOffset_", declaredType="fj9object_t")
1151
* public J9ObjectPointer ref() throws CorruptDataException {
1152
* return getObjectReferenceAtOffset(Example._refOffset_);
1153
* }
1154
*/
1155
private void doFJ9ObjectMethod(FieldDescriptor field) {
1156
Type objectType = Type.getObjectType(qualifyPointerType("J9Object"));
1157
String returnDesc = Type.getMethodDescriptor(objectType);
1158
String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1159
1160
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1161
1162
method.visitCode();
1163
if (checkPresent(field, method)) {
1164
method.visitVarInsn(ALOAD, 0);
1165
loadLong(method, field.getOffset());
1166
method.visitMethodInsn(INVOKEVIRTUAL, className, "getObjectReferenceAtOffset", accessorDesc, false);
1167
method.visitInsn(ARETURN);
1168
}
1169
method.visitMaxs(3, 1);
1170
method.visitEnd();
1171
1172
doEAMethod("ObjectReference", field);
1173
}
1174
1175
/* Sample generated code:
1176
*
1177
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_fieldAddressOffset_", declaredType="const fj9object_t*")
1178
* public ObjectReferencePointer fieldAddress() throws CorruptDataException {
1179
* return ObjectReferencePointer.cast(getPointerAtOffset(J9MM_IterateObjectRefDescriptor._fieldAddressOffset_));
1180
* }
1181
*/
1182
private void doFJ9ObjectPointerMethod(FieldDescriptor field) {
1183
String returnType = qualifyPointerType("ObjectReference");
1184
Type objectType = Type.getObjectType(returnType);
1185
String returnDesc = Type.getMethodDescriptor(objectType);
1186
String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1187
1188
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1189
1190
method.visitCode();
1191
if (checkPresent(field, method)) {
1192
method.visitVarInsn(ALOAD, 0);
1193
loadLong(method, field.getOffset());
1194
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1195
method.visitMethodInsn(INVOKESTATIC, returnType, "cast", castDesc, false);
1196
method.visitInsn(ARETURN);
1197
}
1198
method.visitMaxs(3, 1);
1199
method.visitEnd();
1200
1201
doEAMethod("Pointer", field);
1202
}
1203
1204
/* Sample generated code:
1205
*
1206
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_fOffset_", declaredType="jfloat")
1207
* public float f() throws CorruptDataException {
1208
* return getFloatAtOffset(jvalue._fOffset_);
1209
* }
1210
*/
1211
private void doFloatMethod(FieldDescriptor field) {
1212
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), floatFromVoid);
1213
1214
method.visitCode();
1215
if (checkPresent(field, method)) {
1216
method.visitVarInsn(ALOAD, 0);
1217
loadLong(method, field.getOffset());
1218
method.visitMethodInsn(INVOKEVIRTUAL, className, "getFloatAtOffset", floatFromLong, false);
1219
method.visitInsn(FRETURN);
1220
}
1221
method.visitMaxs(3, 1);
1222
method.visitEnd();
1223
1224
doEAMethod("Float", field);
1225
}
1226
1227
/* Sample generated code:
1228
*
1229
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_clazzOffset_", declaredType="j9objectclass_t")
1230
* public J9ClassPointer clazz() throws CorruptDataException {
1231
* return getObjectClassAtOffset(J9Object._clazzOffset_);
1232
* }
1233
*/
1234
private void doJ9ObjectClassMethod(FieldDescriptor field) {
1235
String returnType = qualifyPointerType("J9Class");
1236
Type objectType = Type.getObjectType(returnType);
1237
String returnDesc = Type.getMethodDescriptor(objectType);
1238
String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1239
1240
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1241
1242
method.visitCode();
1243
if (checkPresent(field, method)) {
1244
method.visitVarInsn(ALOAD, 0);
1245
loadLong(method, field.getOffset());
1246
method.visitMethodInsn(INVOKEVIRTUAL, className, "getObjectClassAtOffset", accessorDesc, false);
1247
method.visitInsn(ARETURN);
1248
}
1249
method.visitMaxs(3, 1);
1250
method.visitEnd();
1251
1252
doEAMethod("ObjectClassReference", field);
1253
}
1254
1255
/* Sample generated code:
1256
*
1257
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_classPtrOffset_", declaredType="j9objectclass_t*")
1258
* public ObjectClassReferencePointer classPtr() throws CorruptDataException {
1259
* return ObjectClassReferencePointer.cast(getPointerAtOffset(Example._classPtrOffset_));
1260
* }
1261
*/
1262
private void doJ9ObjectClassPointerMethod(FieldDescriptor field) {
1263
String returnType = qualifyPointerType("ObjectClassReference");
1264
Type objectType = Type.getObjectType(returnType);
1265
String returnDesc = Type.getMethodDescriptor(objectType);
1266
String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1267
1268
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1269
1270
method.visitCode();
1271
if (checkPresent(field, method)) {
1272
method.visitVarInsn(ALOAD, 0);
1273
loadLong(method, field.getOffset());
1274
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1275
method.visitMethodInsn(INVOKESTATIC, returnType, "cast", accessorDesc, false);
1276
method.visitInsn(ARETURN);
1277
}
1278
method.visitMaxs(3, 1);
1279
method.visitEnd();
1280
1281
doEAMethod("Pointer", field);
1282
}
1283
1284
/* Sample generated code:
1285
*
1286
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_monitorOffset_", declaredType="j9objectmonitor_t")
1287
* public J9ObjectMonitorPointer monitor() throws CorruptDataException {
1288
* return getObjectMonitorAtOffset(Example._monitorOffset_);
1289
* }
1290
*/
1291
private void doJ9ObjectMonitorMethod(FieldDescriptor field) {
1292
String returnType = qualifyPointerType("J9ObjectMonitor");
1293
Type objectType = Type.getObjectType(returnType);
1294
String returnDesc = Type.getMethodDescriptor(objectType);
1295
String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1296
1297
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1298
1299
method.visitCode();
1300
if (checkPresent(field, method)) {
1301
method.visitVarInsn(ALOAD, 0);
1302
loadLong(method, field.getOffset());
1303
method.visitMethodInsn(INVOKEVIRTUAL, className, "getObjectMonitorAtOffset", accessorDesc, false);
1304
method.visitInsn(ARETURN);
1305
}
1306
method.visitMaxs(3, 1);
1307
method.visitEnd();
1308
1309
doEAMethod("ObjectMonitorReference", field);
1310
}
1311
1312
/* Sample generated code:
1313
*
1314
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_lockwordOffset_", declaredType="j9objectmonitor_t*")
1315
* public ObjectMonitorReferencePointer lockword() throws CorruptDataException {
1316
* return ObjectMonitorReferencePointer.cast(getPointerAtOffset(Example._lockwordOffset_));
1317
* }
1318
*/
1319
private void doJ9ObjectMonitorPointerMethod(FieldDescriptor field) {
1320
String returnType = qualifyPointerType("ObjectMonitorReference");
1321
Type objectType = Type.getObjectType(returnType);
1322
String returnDesc = Type.getMethodDescriptor(objectType);
1323
String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1324
1325
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1326
1327
method.visitCode();
1328
if (checkPresent(field, method)) {
1329
method.visitVarInsn(ALOAD, 0);
1330
loadLong(method, field.getOffset());
1331
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1332
method.visitMethodInsn(INVOKESTATIC, returnType, "cast", castDesc, false);
1333
method.visitInsn(ARETURN);
1334
}
1335
method.visitMaxs(3, 1);
1336
method.visitEnd();
1337
1338
doEAMethod("Pointer", field);
1339
}
1340
1341
private void doNullInstance() {
1342
// public static final SELF NULL = new SELF(0);
1343
clazz.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, "NULL", classType.getDescriptor(), null, null).visitEnd();
1344
1345
MethodVisitor clinit = clazz.visitMethod(ACC_STATIC, "<clinit>", voidMethod, null, null);
1346
1347
clinit.visitCode();
1348
clinit.visitTypeInsn(NEW, className);
1349
clinit.visitInsn(DUP);
1350
clinit.visitInsn(LCONST_0);
1351
clinit.visitMethodInsn(INVOKESPECIAL, className, "<init>", voidFromLong, false);
1352
clinit.visitFieldInsn(PUTSTATIC, className, "NULL", classType.getDescriptor());
1353
clinit.visitInsn(RETURN);
1354
clinit.visitMaxs(4, 0);
1355
clinit.visitEnd();
1356
}
1357
1358
/* Sample generated code:
1359
*
1360
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_ramConstantPoolOffset_", declaredType="UDATA*")
1361
* public UDATAPointer ramConstantPool() throws CorruptDataException {
1362
* return UDATAPointer.cast(getPointerAtOffset(J9Class._ramConstantPoolOffset_));
1363
* }
1364
*/
1365
private void doPointerMethod(FieldDescriptor field) {
1366
String targetType = getTargetType(removeTypeTags(field.getType()));
1367
String qualifiedTargetType = qualifyPointerType(targetType);
1368
String castDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedTargetType), Type.LONG_TYPE);
1369
1370
String returnType = generalizeSimpleType(targetType);
1371
String qualifiedReturnType = qualifyPointerType(returnType);
1372
String returnDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedReturnType));
1373
1374
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1375
1376
method.visitCode();
1377
if (checkPresent(field, method)) {
1378
method.visitVarInsn(ALOAD, 0);
1379
loadLong(method, field.getOffset());
1380
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1381
method.visitMethodInsn(INVOKESTATIC, qualifiedTargetType, "cast", castDesc, false);
1382
method.visitInsn(ARETURN);
1383
}
1384
method.visitMaxs(3, 1);
1385
method.visitEnd();
1386
1387
doEAMethod("Pointer", field);
1388
}
1389
1390
/* Sample generated code:
1391
*
1392
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_castClassCacheOffset_", declaredType="UDATA")
1393
* public UDATA castClassCache() throws CorruptDataException {
1394
* return new UDATA(getLongAtOffset(J9Class._castClassCacheOffset_));
1395
* }
1396
*/
1397
private void doSimpleTypeMethod(FieldDescriptor field, int type) {
1398
String fieldType = field.getType();
1399
String returnType = generalizeSimpleType(fieldType);
1400
String qualifiedFieldType = qualifyType(fieldType);
1401
String qualifiedReturnType = qualifyType(returnType);
1402
PrimitiveAccessor accessor = simpleTypeAccessor(type);
1403
String returnDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedReturnType));
1404
1405
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1406
1407
method.visitCode();
1408
if (checkPresent(field, method)) {
1409
method.visitTypeInsn(NEW, qualifiedFieldType);
1410
method.visitInsn(DUP);
1411
method.visitVarInsn(ALOAD, 0);
1412
loadLong(method, field.getOffset());
1413
method.visitMethodInsn(INVOKEVIRTUAL, className, accessor.methodName, accessor.descriptor, false);
1414
if (!accessor.returnsLong) {
1415
method.visitInsn(I2L);
1416
}
1417
method.visitMethodInsn(INVOKESPECIAL, qualifiedFieldType, "<init>", voidFromLong, false);
1418
method.visitInsn(ARETURN);
1419
}
1420
method.visitMaxs(5, 1);
1421
method.visitEnd();
1422
1423
doEAMethod(fieldType, field);
1424
}
1425
1426
/* Sample generated code:
1427
*
1428
* public WideSelfRelativePointer puddleListEA() throws CorruptDataException {
1429
* return WideSelfRelativePointer.cast(nonNullFieldEA(J9Pool._puddleListOffset_));
1430
* }
1431
*/
1432
private void doSRPEAMethod(FieldDescriptor field, boolean isWide) {
1433
String accessorName = field.getName() + "EA";
1434
String returnTypeName = qualifyPointerType(isWide ? "WideSelfRelative" : "SelfRelative");
1435
Type returnType = Type.getObjectType(returnTypeName);
1436
String returnDesc = Type.getMethodDescriptor(returnType);
1437
String castDesc = Type.getMethodDescriptor(returnType, Type.LONG_TYPE);
1438
1439
MethodVisitor method = beginMethod(field, accessorName, returnDesc);
1440
1441
method.visitCode();
1442
if (checkPresent(field, method)) {
1443
method.visitVarInsn(ALOAD, 0);
1444
loadLong(method, field.getOffset());
1445
method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);
1446
method.visitMethodInsn(INVOKESTATIC, returnTypeName, "cast", castDesc, false);
1447
method.visitInsn(ARETURN);
1448
}
1449
method.visitMaxs(3, 1);
1450
method.visitEnd();
1451
}
1452
1453
/* Sample generated code:
1454
*
1455
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_annotationDataOffset_", declaredType="J9SRP(UDATA)")
1456
* public UDATAPointer annotationData() throws CorruptDataException {
1457
* int srp = getIntAtOffset(J9AnnotationInfoEntry._annotationDataOffset_);
1458
* if (srp == 0) {
1459
* return UDATAPointer.NULL;
1460
* }
1461
* return UDATAPointer.cast(address + J9AnnotationInfoEntry._annotationDataOffset_ + srp);
1462
* }
1463
*/
1464
private void doSRPMethod(FieldDescriptor field, boolean isWide) {
1465
final String prefix = isWide ? "J9WSRP" : "J9SRP";
1466
final int prefixLength = prefix.length();
1467
final String rawFieldType = field.getType();
1468
String targetType;
1469
1470
if (rawFieldType.startsWith(prefix) && rawFieldType.startsWith("(", prefixLength)) {
1471
targetType = rawFieldType.substring(prefixLength + 1, rawFieldType.length() - 1).trim();
1472
} else {
1473
targetType = "void";
1474
}
1475
1476
int type = typeManager.getType(targetType);
1477
1478
switch (type) {
1479
case StructureTypeManager.TYPE_J9SRP:
1480
targetType = "SelfRelative";
1481
break;
1482
case StructureTypeManager.TYPE_J9WSRP:
1483
targetType = "WideSelfRelative";
1484
break;
1485
case StructureTypeManager.TYPE_STRUCTURE:
1486
targetType = removeTypeTags(targetType);
1487
break;
1488
case StructureTypeManager.TYPE_VOID:
1489
targetType = "Void";
1490
break;
1491
default:
1492
if ((StructureTypeManager.TYPE_SIMPLE_MIN <= type) && (type <= StructureTypeManager.TYPE_SIMPLE_MAX)) {
1493
targetType = removeTypeTags(targetType);
1494
} else {
1495
throw new IllegalArgumentException("Unexpected SRP type: " + rawFieldType);
1496
}
1497
break;
1498
}
1499
1500
String returnTypeName = qualifyPointerType(generalizeSimpleType(targetType));
1501
Type returnType = Type.getObjectType(returnTypeName);
1502
String returnDesc = Type.getMethodDescriptor(returnType);
1503
String qualifiedPointerName = qualifyPointerType(targetType);
1504
String qualifiedPointerDesc = Type.getObjectType(qualifiedPointerName).getDescriptor();
1505
1506
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1507
1508
method.visitCode();
1509
if (checkPresent(field, method)) {
1510
Label nonNull = new Label();
1511
1512
method.visitVarInsn(ALOAD, 0);
1513
loadLong(method, field.getOffset());
1514
1515
if (isWide) {
1516
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1517
method.visitVarInsn(LSTORE, 1);
1518
1519
method.visitVarInsn(LLOAD, 1);
1520
method.visitInsn(LCONST_0);
1521
method.visitInsn(LCMP);
1522
} else {
1523
method.visitMethodInsn(INVOKEVIRTUAL, className, "getIntAtOffset", intFromLong, false);
1524
method.visitVarInsn(ISTORE, 1);
1525
1526
method.visitVarInsn(ILOAD, 1);
1527
}
1528
method.visitJumpInsn(IFNE, nonNull);
1529
1530
method.visitFieldInsn(GETSTATIC, qualifiedPointerName, "NULL", qualifiedPointerDesc);
1531
method.visitInsn(ARETURN);
1532
1533
method.visitLabel(nonNull);
1534
method.visitFrame(F_APPEND, 1, new Object[] { isWide ? LONG : INTEGER }, 0, null);
1535
method.visitVarInsn(ALOAD, 0);
1536
method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());
1537
addLong(method, field.getOffset());
1538
if (isWide) {
1539
method.visitVarInsn(LLOAD, 1);
1540
} else {
1541
method.visitVarInsn(ILOAD, 1);
1542
method.visitInsn(I2L);
1543
}
1544
method.visitInsn(LADD);
1545
1546
String castDesc = Type.getMethodDescriptor(returnType, Type.LONG_TYPE);
1547
1548
method.visitMethodInsn(INVOKESTATIC, qualifiedPointerName, "cast", castDesc, false);
1549
method.visitInsn(ARETURN);
1550
}
1551
method.visitMaxs(4, isWide ? 3 : 2);
1552
method.visitEnd();
1553
1554
doSRPEAMethod(field, isWide);
1555
}
1556
1557
/* Sample generated code:
1558
*
1559
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_sharedHeadNodePtrOffset_", declaredType="J9SRP*")
1560
* public SelfRelativePointer sharedHeadNodePtr() throws CorruptDataException {
1561
* return SelfRelativePointer.cast(getPointerAtOffset(J9SharedInvariantInternTable._sharedHeadNodePtrOffset_));
1562
* }
1563
*/
1564
private void doSRPPointerMethod(FieldDescriptor field, boolean wide) {
1565
String returnType = qualifyPointerType(wide ? "WideSelfRelative" : "SelfRelative");
1566
Type objectType = Type.getObjectType(returnType);
1567
String returnDesc = Type.getMethodDescriptor(objectType);
1568
String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1569
1570
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1571
1572
method.visitCode();
1573
if (checkPresent(field, method)) {
1574
method.visitVarInsn(ALOAD, 0);
1575
loadLong(method, field.getOffset());
1576
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1577
method.visitMethodInsn(INVOKESTATIC, returnType, "cast", castDesc, false);
1578
method.visitInsn(ARETURN);
1579
}
1580
method.visitMaxs(3, 1);
1581
method.visitEnd();
1582
1583
doEAMethod("Pointer", field);
1584
}
1585
1586
/* Sample generated code:
1587
*
1588
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_permOffset_", declaredType="J9Permission")
1589
* public J9PermissionPointer perm() throws CorruptDataException {
1590
* return J9PermissionPointer.cast(nonNullFieldEA(J9FileStat._permOffset_));
1591
* }
1592
*/
1593
private void doStructureMethod(FieldDescriptor field) {
1594
String fieldType = removeTypeTags(field.getType());
1595
String returnType = "void".equals(fieldType) ? "Void" : fieldType;
1596
String qualifiedReturnType = qualifyPointerType(returnType);
1597
Type objectType = Type.getObjectType(qualifiedReturnType);
1598
String returnDesc = Type.getMethodDescriptor(objectType);
1599
String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1600
1601
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1602
1603
method.visitCode();
1604
if (checkPresent(field, method)) {
1605
method.visitVarInsn(ALOAD, 0);
1606
loadLong(method, field.getOffset());
1607
method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);
1608
method.visitMethodInsn(INVOKESTATIC, qualifiedReturnType, "cast", castDesc, false);
1609
method.visitInsn(ARETURN);
1610
}
1611
method.visitMaxs(3, 1);
1612
method.visitEnd();
1613
1614
doEAMethod("Pointer", field);
1615
}
1616
1617
/* Sample generated code:
1618
*
1619
* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_hostClassOffset_", declaredType="J9Class*")
1620
* public J9ClassPointer hostClass() throws CorruptDataException {
1621
* return J9ClassPointer.cast(getPointerAtOffset(J9Class._hostClassOffset_));
1622
* }
1623
*/
1624
private void doStructurePointerMethod(FieldDescriptor field) {
1625
String returnType = getTargetType(removeTypeTags(field.getType()));
1626
String qualifiedReturnType = qualifyPointerType(returnType);
1627
Type objectType = Type.getObjectType(qualifiedReturnType);
1628
String returnDesc = Type.getMethodDescriptor(objectType);
1629
String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);
1630
1631
MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);
1632
1633
method.visitCode();
1634
if (checkPresent(field, method)) {
1635
method.visitVarInsn(ALOAD, 0);
1636
loadLong(method, field.getOffset());
1637
method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);
1638
method.visitMethodInsn(INVOKESTATIC, qualifiedReturnType, "cast", castDesc, false);
1639
method.visitInsn(ARETURN);
1640
}
1641
method.visitMaxs(3, 1);
1642
method.visitEnd();
1643
1644
doEAMethod("Pointer", field);
1645
}
1646
1647
private byte[] generate() {
1648
String superClassName = structure.getSuperName();
1649
1650
if (superClassName.isEmpty()) {
1651
superClassName = basePrefix + "pointer/StructurePointer";
1652
} else {
1653
superClassName = basePrefix + "pointer/generated/" + superClassName + "Pointer";
1654
}
1655
1656
clazz.visit(V1_8, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, null);
1657
1658
doClassAnnotation();
1659
doNullInstance();
1660
doConstructors(superClassName);
1661
doAccessorMethods();
1662
1663
clazz.visitEnd();
1664
1665
return clazz.toByteArray();
1666
}
1667
1668
private String getStructureClassName() {
1669
return basePrefix + "structure/" + structure.getName();
1670
}
1671
1672
private String qualifyPointerType(String type) {
1673
String subPackage = predefinedPointerTypes.contains(type) ? "pointer/" : "pointer/generated/";
1674
1675
return basePrefix + subPackage + type + "Pointer";
1676
}
1677
1678
private String qualifyType(String type) {
1679
String subPackage = predefinedDataTypes.contains(type) ? "types/" : "structure/";
1680
1681
return basePrefix + subPackage + type;
1682
}
1683
1684
private PrimitiveAccessor simpleTypeAccessor(int type) {
1685
int size;
1686
1687
switch (type) {
1688
case StructureTypeManager.TYPE_I8:
1689
case StructureTypeManager.TYPE_U8:
1690
size = 1;
1691
break;
1692
case StructureTypeManager.TYPE_I16:
1693
case StructureTypeManager.TYPE_U16:
1694
size = 2;
1695
break;
1696
case StructureTypeManager.TYPE_I32:
1697
case StructureTypeManager.TYPE_U32:
1698
size = 4;
1699
break;
1700
case StructureTypeManager.TYPE_I64:
1701
case StructureTypeManager.TYPE_U64:
1702
size = 8;
1703
break;
1704
case StructureTypeManager.TYPE_IDATA:
1705
case StructureTypeManager.TYPE_UDATA:
1706
size = reader.getSizeOfUDATA();
1707
break;
1708
default:
1709
throw new IllegalArgumentException("type=" + type);
1710
}
1711
1712
return PrimitiveAccessor.forSize(size);
1713
}
1714
1715
}
1716
1717
enum PrimitiveAccessor {
1718
1719
BYTE("getByteAtOffset", HelperBase.byteFromLong, false),
1720
1721
INT("getIntAtOffset", HelperBase.intFromLong, false),
1722
1723
LONG("getLongAtOffset", HelperBase.longFromLong, true),
1724
1725
SHORT("getShortAtOffset", HelperBase.shortFromLong, false);
1726
1727
static PrimitiveAccessor forSize(int size) {
1728
switch (size) {
1729
case 1:
1730
return BYTE;
1731
case 2:
1732
return SHORT;
1733
case 4:
1734
return INT;
1735
case 8:
1736
return LONG;
1737
default:
1738
throw new IllegalArgumentException("size=" + size);
1739
}
1740
}
1741
1742
final String descriptor;
1743
1744
final String methodName;
1745
1746
final boolean returnsLong;
1747
1748
PrimitiveAccessor(String methodName, String descriptor, boolean returnsLong) {
1749
this.methodName = methodName;
1750
this.descriptor = descriptor;
1751
this.returnsLong = returnsLong;
1752
}
1753
1754
}
1755
1756
final class StructureHelper extends HelperBase {
1757
1758
static byte[] getClassBytes(StructureDescriptor structure, String className) {
1759
StructureHelper helper = new StructureHelper(structure, className);
1760
1761
return helper.generate();
1762
}
1763
1764
private final String className;
1765
1766
private final ClassWriter clazz;
1767
1768
private final MethodVisitor clinit;
1769
1770
private final StructureDescriptor structure;
1771
1772
private StructureHelper(StructureDescriptor structure, String className) {
1773
super();
1774
this.className = className;
1775
this.clazz = new ClassWriter(0);
1776
this.clazz.visit(V1_8, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, className, null, "java/lang/Object", null);
1777
this.clinit = clazz.visitMethod(ACC_STATIC, "<clinit>", voidMethod, null, null);
1778
this.clinit.visitCode();
1779
this.structure = structure;
1780
}
1781
1782
private void defineField(String name, Type type, long value) {
1783
String typeDescriptor = type.getDescriptor();
1784
1785
clazz.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, name, typeDescriptor, null, null).visitEnd();
1786
1787
if (type.getSort() == Type.INT) {
1788
loadInt(clinit, (int) value);
1789
} else {
1790
loadLong(clinit, value);
1791
}
1792
1793
clinit.visitFieldInsn(PUTSTATIC, className, name, typeDescriptor);
1794
}
1795
1796
private void defineFields() {
1797
defineField("SIZEOF", Type.LONG_TYPE, structure.getSizeOf());
1798
1799
// other constants
1800
for (ConstantDescriptor constant : structure.getConstants()) {
1801
defineField(constant.getName(), Type.LONG_TYPE, constant.getValue());
1802
}
1803
1804
// offsets
1805
int bitFieldBitCount = 0;
1806
for (FieldDescriptor field : structure.getFields()) {
1807
if (!field.isPresent()) {
1808
continue;
1809
}
1810
1811
String fieldName = field.getName();
1812
int fieldOffset = field.getOffset();
1813
String type = field.getType();
1814
int colonIndex = type.lastIndexOf(':');
1815
1816
// make sure match a bitfield, not a C++ namespace
1817
if (colonIndex <= 0 || type.charAt(colonIndex - 1) == ':') {
1818
// regular offset field
1819
defineField(String.format("_%sOffset_", fieldName), Type.INT_TYPE, fieldOffset);
1820
} else {
1821
// bitfield
1822
int bitSize = Integer.parseInt(type.substring(colonIndex + 1).trim());
1823
1824
/*
1825
* Newer blobs have accurate offsets of bitfields; adjust bitFieldBitCount
1826
* to account for any fields preceding this field. In older blobs the byte
1827
* offset of a bitfield is always zero, so this has no effect.
1828
*/
1829
bitFieldBitCount = Math.max(bitFieldBitCount, fieldOffset * Byte.SIZE);
1830
1831
if (bitSize > (StructureReader.BIT_FIELD_CELL_SIZE
1832
- (bitFieldBitCount % StructureReader.BIT_FIELD_CELL_SIZE))) {
1833
throw new InternalError(
1834
String.format("Bitfield %s->%s must not span cells", structure.getName(), fieldName));
1835
}
1836
1837
// 's' field
1838
defineField(String.format("_%s_s_", fieldName), Type.INT_TYPE, bitFieldBitCount);
1839
1840
// 'b' field
1841
defineField(String.format("_%s_b_", fieldName), Type.INT_TYPE, bitSize);
1842
1843
bitFieldBitCount += bitSize;
1844
}
1845
}
1846
1847
clinit.visitInsn(RETURN);
1848
clinit.visitMaxs(2, 0);
1849
clinit.visitEnd();
1850
}
1851
1852
private byte[] generate() {
1853
defineFields();
1854
1855
MethodVisitor method = clazz.visitMethod(ACC_PUBLIC, "<init>", voidMethod, null, null);
1856
1857
method.visitCode();
1858
method.visitVarInsn(ALOAD, 0);
1859
method.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", voidMethod, false);
1860
method.visitInsn(RETURN);
1861
method.visitMaxs(1, 1);
1862
method.visitEnd();
1863
1864
clazz.visitEnd();
1865
1866
return clazz.toByteArray();
1867
}
1868
1869
}
1870
1871