Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/BytecodeGenerator.java
6004 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/21package com.ibm.j9ddr;2223import java.util.Arrays;24import java.util.HashMap;25import java.util.HashSet;26import java.util.Map;27import java.util.Set;28import java.util.TreeMap;29import java.util.regex.Pattern;3031import com.ibm.j9ddr.StructureReader.ConstantDescriptor;32import com.ibm.j9ddr.StructureReader.FieldDescriptor;33import com.ibm.j9ddr.StructureReader.StructureDescriptor;34import com.ibm.j9ddr.tools.FlagStructureList;3536import jdk.internal.org.objectweb.asm.AnnotationVisitor;37import jdk.internal.org.objectweb.asm.ClassWriter;38import jdk.internal.org.objectweb.asm.Label;39import jdk.internal.org.objectweb.asm.MethodVisitor;40import jdk.internal.org.objectweb.asm.Opcodes;41import jdk.internal.org.objectweb.asm.Type;4243/**44* Generates the class bytecodes needed by DDR to represent, as Java classes,45* the structures and pointers described by the blob.46*/47public class BytecodeGenerator {4849private static void addFlagAlias(Map<String, String> map, String name, String alias) {50if (map.get(name) == null) {51map.put(name, alias);52}53}5455private static Map<String, String> addFlagAliasesFor(Map<String, String> map, String className) {56/*57* The DDR tools from OMR, normally generate constants with names as they58* appear in the source code. Unfortunately, the legacy tools used in IBM59* builds yield different names for 'build flags'. A field override was60* added to provide compatibility with those legacy tools for s39061* J9VM_ARCH_S390=arch_s39062* but not for other architectures. J9ConfigFlags was introduced in an63* attempt to handle this difference in naming convention, but it64* incorrectly assumed the fields it referenced would be dynamically65* generated according to the blob found in the associated core file,66* rather than being fixed at build time. The set of aliases here replaces67* the ineffective mapping in J9ConfigFlags.68* The result is that OpenJ9 builds have additional fields in J9BuildFlags69* that are copied from the OMR-derived names. For example, arch_x86 is70* present when the legacy tools are used; when OMR tools are used, arch_x8671* is a copy of J9VM_ARCH_X86.72*73* Note: Do not add new aliases to this map. Instead, add overrides like74* was done for arch_s390 to retain compatibility with the legacy tools.75*/76if (className.equals("J9BuildFlags")) {77addFlagAlias(map, "arch_arm", "J9VM_ARCH_ARM");78addFlagAlias(map, "arch_aarch64", "J9VM_ARCH_AARCH64");79addFlagAlias(map, "arch_power", "J9VM_ARCH_POWER");80addFlagAlias(map, "arch_riscv", "J9VM_ARCH_RISCV");81addFlagAlias(map, "arch_x86", "J9VM_ARCH_X86");82}83return map;84}8586static Map<String, String> getFlagAliasesFor(String className) {87return addFlagAliasesFor(new HashMap<String, String>(), className);88}8990public static Map<String, String> getConstantsAndAliases(StructureDescriptor structure) {91Map<String, String> map = new TreeMap<>();9293for (ConstantDescriptor constant : structure.getConstants()) {94String name = constant.getName();9596map.put(name, null);97}9899return addFlagAliasesFor(map, structure.getName());100}101102public static byte[] getPointerClassBytes(StructureReader reader, StructureTypeManager typeManager,103StructureDescriptor structure, String className) {104if (FlagStructureList.isFlagsStructure(structure.getName())) {105return FlagsHelper.getClassBytes(structure, className);106} else {107return PointerHelper.getClassBytes(reader, typeManager, structure, className);108}109}110111public static byte[] getStructureClassBytes(StructureDescriptor structure, String className) {112return StructureHelper.getClassBytes(structure, className);113}114115}116117final class FlagsHelper extends HelperBase {118119public static byte[] getClassBytes(StructureDescriptor structure, String className) {120ClassWriter clazz = new ClassWriter(0);121122clazz.visit(V1_8, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, className, null, "java/lang/Object", null);123124MethodVisitor clinit = clazz.visitMethod(ACC_STATIC, "<clinit>", voidMethod, null, null);125126clinit.visitCode();127128Map<String, Boolean> values = new TreeMap<>();129130for (ConstantDescriptor constant : structure.getConstants()) {131String name = constant.getName();132133values.put(name, Boolean.valueOf(constant.getValue() != 0));134}135136Map<String, String> aliases = BytecodeGenerator.getFlagAliasesFor(structure.getName());137138for (Map.Entry<String, String> entry : aliases.entrySet()) {139String name = entry.getKey();140141if (Boolean.TRUE.equals(values.get(name))) {142continue;143}144145Boolean value = values.get(entry.getValue());146147if (value == null) {148value = Boolean.FALSE;149}150151values.put(name, value);152}153154for (Map.Entry<String, Boolean> entry : values.entrySet()) {155String name = entry.getKey();156Boolean value = entry.getValue();157158clazz.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, name, "Z", null, null).visitEnd();159160clinit.visitInsn(value.booleanValue() ? ICONST_1 : ICONST_0);161clinit.visitFieldInsn(PUTSTATIC, className, name, Type.BOOLEAN_TYPE.getDescriptor());162}163164clinit.visitInsn(RETURN);165clinit.visitMaxs(1, 0);166clinit.visitEnd();167168MethodVisitor method = clazz.visitMethod(ACC_PRIVATE, "<init>", voidMethod, null, null);169170method.visitCode();171method.visitVarInsn(ALOAD, 0);172method.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", voidMethod, false);173method.visitInsn(RETURN);174method.visitMaxs(1, 1);175method.visitEnd();176177clazz.visitEnd();178179return clazz.toByteArray();180}181182}183184abstract class HelperBase implements Opcodes {185186static final String byteFromLong = Type.getMethodDescriptor(Type.BYTE_TYPE, Type.LONG_TYPE);187188static final String doubleFromLong = Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.LONG_TYPE);189190static final String doubleFromVoid = Type.getMethodDescriptor(Type.DOUBLE_TYPE);191192static final String floatFromLong = Type.getMethodDescriptor(Type.FLOAT_TYPE, Type.LONG_TYPE);193194static final String floatFromVoid = Type.getMethodDescriptor(Type.FLOAT_TYPE);195196static final String intFromLong = Type.getMethodDescriptor(Type.INT_TYPE, Type.LONG_TYPE);197198static final String longFromLong = Type.getMethodDescriptor(Type.LONG_TYPE, Type.LONG_TYPE);199200static final String longFromVoid = Type.getMethodDescriptor(Type.LONG_TYPE);201202static final String shortFromLong = Type.getMethodDescriptor(Type.SHORT_TYPE, Type.LONG_TYPE);203204static final String voidFromLong = Type.getMethodDescriptor(Type.VOID_TYPE, Type.LONG_TYPE);205206static final String voidMethod = Type.getMethodDescriptor(Type.VOID_TYPE);207208static final void addLong(MethodVisitor method, long value) {209if (value != 0) {210loadLong(method, value);211method.visitInsn(LADD);212}213}214215static final void loadInt(MethodVisitor method, int value) {216switch (value) {217case -1:218method.visitInsn(ICONST_M1);219break;220case 0:221method.visitInsn(ICONST_0);222break;223case 1:224method.visitInsn(ICONST_1);225break;226case 2:227method.visitInsn(ICONST_2);228break;229case 3:230method.visitInsn(ICONST_3);231break;232case 4:233method.visitInsn(ICONST_4);234break;235case 5:236method.visitInsn(ICONST_5);237break;238default:239method.visitLdcInsn(Integer.valueOf(value));240break;241}242}243244static final void loadLong(MethodVisitor method, long value) {245if (value == 0) {246method.visitInsn(LCONST_0);247} else if (value == 1) {248method.visitInsn(LCONST_1);249} else {250method.visitLdcInsn(Long.valueOf(value));251}252}253254}255256final class PointerHelper extends HelperBase {257258private static final Pattern ConstPattern = Pattern.compile("\\s*\\bconst\\s+");259260private static final Set<String> predefinedDataTypes;261262private static final Set<String> predefinedPointerTypes;263264private static final Pattern TypeTagPattern = Pattern.compile("\\s*\\b(class|enum|struct)\\s+");265266static {267Set<String> common = addNames(new HashSet<String>(), "I8 U8 I16 U16 I32 U32 I64 U64 IDATA UDATA Void");268269predefinedDataTypes = new HashSet<String>(common);270addNames(predefinedDataTypes, "Scalar IScalar UScalar");271272predefinedPointerTypes = new HashSet<String>(common);273addNames(predefinedPointerTypes, "Abstract Bool Double Enum Float ObjectClassReference ObjectMonitorReference");274addNames(predefinedPointerTypes, "ObjectReference Pointer SelfRelative Structure WideSelfRelative");275}276277private static Set<String> addNames(Set<String> set, String names) {278set.addAll(Arrays.asList(names.split(" ")));279return set;280}281282private static boolean checkPresent(FieldDescriptor field, MethodVisitor method) {283if (field.isPresent()) {284return true;285}286287String noSuchField = "java/lang/NoSuchFieldException";288289method.visitTypeInsn(NEW, noSuchField);290method.visitInsn(DUP);291method.visitMethodInsn(INVOKESPECIAL, noSuchField, "<init>", voidMethod, false);292293method.visitInsn(ATHROW);294295return false;296}297298/*299* The new DDR tooling doesn't always distinguish between IDATA and I32 or I64300* or between UDATA and U32 or U64. Thus the return types of accessor methods301* must be more general to be compatible with the pointer types derived from302* both 32-bit and 64-bit core files. This generalization must occur even for303* the pointer stubs generated from this code so that incompatibilities will304* be discovered at build time, rather than at run time.305*/306private static String generalizeSimpleType(String type) {307if ("I32".equals(type) || "I64".equals(type)) {308return "IDATA";309} else if ("U32".equals(type) || "U64".equals(type)) {310return "UDATA";311} else {312return type;313}314}315316static byte[] getClassBytes(StructureReader reader, StructureTypeManager typeManager, StructureDescriptor structure,317String className) {318PointerHelper helper = new PointerHelper(reader, typeManager, structure, className);319320return helper.generate();321}322323private static String getEnumType(String enumType) {324int start = enumType.startsWith("enum ") ? 5 : 0;325int end = enumType.length();326327if (enumType.endsWith("[]")) {328end -= 2;329}330331return enumType.substring(start, end);332}333334private static String getTargetType(String pointerType) {335String type = ConstPattern.matcher(pointerType).replaceAll("").trim();336int firstStar = type.indexOf('*');337338if (type.indexOf('*', firstStar + 1) > 0) {339// two or more levels of indirection340return "Pointer";341}342343type = type.substring(0, firstStar).trim();344345if (type.equals("bool")) {346return "Bool";347} else if (type.equals("double")) {348return "Double";349} else if (type.equals("float")) {350return "Float";351} else if (type.equals("void")) {352return "Void";353} else {354return type;355}356}357358private static String removeTypeTags(String type) {359return TypeTagPattern.matcher(type).replaceAll("").trim();360}361362private final Type abstractPointerType;363364private final String basePrefix;365366private final String className;367368private final Type classType;369370private final ClassWriter clazz;371372private final String[] normalThrows;373374private final String[] optionalThrows;375376private final StructureReader reader;377378private final Type scalarType;379380private final StructureDescriptor structure;381382private final StructureTypeManager typeManager;383384private final Type udataType;385386private PointerHelper(StructureReader reader, StructureTypeManager typeManager, StructureDescriptor structure,387String className) {388super();389390int index = className.indexOf("/pointer/generated/");391392if (index <= 0) {393throw new IllegalArgumentException(className);394}395396String prefix = className.substring(0, index + 1); // ends with '/vmNN/'397398this.abstractPointerType = Type.getObjectType(prefix + "pointer/AbstractPointer");399this.basePrefix = prefix;400this.className = className;401this.classType = Type.getObjectType(className);402this.clazz = new ClassWriter(0);403this.normalThrows = new String[] { "com/ibm/j9ddr/CorruptDataException" };404this.optionalThrows = new String[] { "com/ibm/j9ddr/CorruptDataException", "java/lang/NoSuchFieldException" };405this.reader = reader;406this.scalarType = Type.getObjectType(prefix + "types/Scalar");407this.structure = structure;408this.typeManager = typeManager;409this.udataType = Type.getObjectType(prefix + "types/UDATA");410}411412private MethodVisitor beginAnnotatedMethod(FieldDescriptor field, String name, String descriptor) {413MethodVisitor method = beginMethod(field, name, descriptor);414415if (field.isPresent()) {416Type annotationType = Type.getObjectType("com/ibm/j9ddr/GeneratedFieldAccessor");417AnnotationVisitor annotation = method.visitAnnotation(annotationType.getDescriptor(), true);418419annotation.visit("offsetFieldName", String.format("_%sOffset_", field.getName()));420annotation.visit("declaredType", field.getDeclaredType());421annotation.visitEnd();422}423424return method;425}426427private MethodVisitor beginMethod(FieldDescriptor field, String name, String descriptor) {428String[] exceptions = field.isOptional() ? optionalThrows : normalThrows;429430return clazz.visitMethod(ACC_PUBLIC, name, descriptor, null, exceptions);431}432433private void doAccessorMethods() {434for (FieldDescriptor field : structure.getFields()) {435String fieldName = field.getName();436437if (fieldName.isEmpty() || fieldName.indexOf('#') >= 0) {438// Omit anonymous fields (xlc generates names containing '#').439continue;440}441442String typeName = field.getType();443int type = typeManager.getType(typeName);444445switch (type) {446case StructureTypeManager.TYPE_STRUCTURE:447doStructureMethod(field);448break;449case StructureTypeManager.TYPE_STRUCTURE_POINTER:450doStructurePointerMethod(field);451break;452case StructureTypeManager.TYPE_POINTER:453doPointerMethod(field);454break;455case StructureTypeManager.TYPE_ARRAY:456doArrayMethod(field);457break;458case StructureTypeManager.TYPE_J9SRP:459doSRPMethod(field, false);460break;461case StructureTypeManager.TYPE_J9WSRP:462doSRPMethod(field, true);463break;464case StructureTypeManager.TYPE_J9SRP_POINTER:465doSRPPointerMethod(field, false);466break;467case StructureTypeManager.TYPE_J9WSRP_POINTER:468doSRPPointerMethod(field, true);469break;470case StructureTypeManager.TYPE_FJ9OBJECT:471doFJ9ObjectMethod(field);472break;473case StructureTypeManager.TYPE_FJ9OBJECT_POINTER:474doFJ9ObjectPointerMethod(field);475break;476case StructureTypeManager.TYPE_J9OBJECTCLASS:477doJ9ObjectClassMethod(field);478break;479case StructureTypeManager.TYPE_J9OBJECTCLASS_POINTER:480doJ9ObjectClassPointerMethod(field);481break;482case StructureTypeManager.TYPE_J9OBJECTMONITOR:483doJ9ObjectMonitorMethod(field);484break;485case StructureTypeManager.TYPE_J9OBJECTMONITOR_POINTER:486doJ9ObjectMonitorPointerMethod(field);487break;488case StructureTypeManager.TYPE_VOID:489doStructureMethod(field);490break;491case StructureTypeManager.TYPE_BOOL:492doBooleanMethod(field);493break;494case StructureTypeManager.TYPE_DOUBLE:495doDoubleMethod(field);496break;497case StructureTypeManager.TYPE_FLOAT:498doFloatMethod(field);499break;500case StructureTypeManager.TYPE_ENUM:501doEnumMethod(field);502break;503case StructureTypeManager.TYPE_ENUM_POINTER:504doEnumPointerMethod(field);505break;506case StructureTypeManager.TYPE_BITFIELD:507int colonIndex = typeName.indexOf(':');508if (colonIndex <= 0) {509throw new IllegalArgumentException(String.format("%s.%s : %s is not a valid bitfield",510structure.getName(), fieldName, typeName));511}512String baseType = typeName.substring(0, colonIndex);513int width = Integer.parseInt(typeName.substring(colonIndex + 1));514doBitfieldMethod(field, baseType, width);515break;516517default:518if ((StructureTypeManager.TYPE_SIMPLE_MIN <= type) && (type <= StructureTypeManager.TYPE_SIMPLE_MAX)) {519doSimpleTypeMethod(field, type);520} else {521// omit unhandled field type522}523break;524}525}526}527528/* Sample generated code:529*530* public ObjectMonitorReferencePointer objectMonitorLookupCacheEA() throws CorruptDataException {531* return ObjectMonitorReferencePointer.cast(nonNullFieldEA(J9VMThread._objectMonitorLookupCacheOffset_));532* }533*/534private void doArrayMethod(FieldDescriptor field) {535String fieldType = field.getType();536String componentType = fieldType.substring(0, fieldType.lastIndexOf('[')).trim();537int type = typeManager.getType(componentType);538539switch (type) {540case StructureTypeManager.TYPE_BOOL:541doEAMethod("Bool", field);542return;543case StructureTypeManager.TYPE_DOUBLE:544doEAMethod("Double", field);545return;546case StructureTypeManager.TYPE_ENUM:547doEnumEAMethod(field);548return;549case StructureTypeManager.TYPE_FLOAT:550doEAMethod("Float", field);551return;552case StructureTypeManager.TYPE_FJ9OBJECT:553doEAMethod("ObjectReference", field);554return;555case StructureTypeManager.TYPE_J9OBJECTCLASS:556doEAMethod("ObjectClassReference", field);557return;558case StructureTypeManager.TYPE_J9OBJECTMONITOR:559doEAMethod("ObjectMonitorReference", field);560return;561case StructureTypeManager.TYPE_STRUCTURE:562doEAMethod(removeTypeTags(componentType), field);563return;564case StructureTypeManager.TYPE_ARRAY:565case StructureTypeManager.TYPE_FJ9OBJECT_POINTER:566case StructureTypeManager.TYPE_J9OBJECTCLASS_POINTER:567case StructureTypeManager.TYPE_J9OBJECTMONITOR_POINTER:568case StructureTypeManager.TYPE_POINTER:569case StructureTypeManager.TYPE_STRUCTURE_POINTER:570// All these pointer types look the same.571doEAMethod("Pointer", field);572return;573default:574if ((StructureTypeManager.TYPE_SIMPLE_MIN <= type) && (type <= StructureTypeManager.TYPE_SIMPLE_MAX)) {575doEAMethod(componentType, field);576return;577}578break;579case StructureTypeManager.TYPE_BITFIELD: // Is a bitfield array even legal?580case StructureTypeManager.TYPE_J9SRP: // not implemented581case StructureTypeManager.TYPE_J9WSRP: // not implemented582break;583}584585throw new IllegalArgumentException("Unrecognized array: " + fieldType);586}587588/* Sample generated code:589*590* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_isDirOffset_", declaredType="uint32_t:1")591* public UDATA isDir() throws CorruptDataException {592* return getU32Bitfield(J9FileStat._isDir_s_, J9FileStat._isDir_b_);593* }594*/595private void doBitfieldMethod(FieldDescriptor field, String baseType, int width) {596String fieldName = field.getName();597Type qualifiedBaseType = Type.getObjectType(qualifyType(baseType));598Type qualifiedReturnType = Type.getObjectType(qualifyType(generalizeSimpleType(baseType)));599String returnDesc = Type.getMethodDescriptor(qualifiedReturnType);600String startFieldName = String.format("_%s_s_", fieldName);601String accessorName = String.format("get%sBitfield", baseType);602String accessorDesc = Type.getMethodDescriptor(qualifiedBaseType, Type.INT_TYPE, Type.INT_TYPE);603604MethodVisitor method = beginAnnotatedMethod(field, fieldName, returnDesc);605606method.visitCode();607if (checkPresent(field, method)) {608method.visitVarInsn(ALOAD, 0);609method.visitFieldInsn(GETSTATIC, getStructureClassName(), startFieldName, Type.INT_TYPE.getDescriptor());610loadInt(method, width);611method.visitMethodInsn(INVOKEVIRTUAL, className, accessorName, accessorDesc, false);612method.visitInsn(ARETURN);613}614method.visitMaxs(3, 1);615method.visitEnd();616617// no EA method for a bitfield618}619620/* Sample generated code:621*622* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="__isAnonOffset_", declaredType="bool")623* public boolean _isAnon() throws CorruptDataException {624* return getBoolAtOffset(ClassFileWriter.__isAnonOffset_);625* }626*/627private void doBooleanMethod(FieldDescriptor field) {628String returnDesc = Type.getMethodDescriptor(Type.BOOLEAN_TYPE);629String accessorDesc = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.LONG_TYPE);630631MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);632633method.visitCode();634if (checkPresent(field, method)) {635method.visitVarInsn(ALOAD, 0);636loadLong(method, field.getOffset());637method.visitMethodInsn(INVOKEVIRTUAL, className, "getBoolAtOffset", accessorDesc, false);638method.visitInsn(IRETURN);639}640method.visitMaxs(3, 1);641method.visitEnd();642643doEAMethod("Bool", field);644}645646private void doClassAnnotation() {647// @com.ibm.j9ddr.GeneratedPointerClass(structureClass=BASE.class)648Type annotationType = Type.getObjectType("com/ibm/j9ddr/GeneratedPointerClass");649AnnotationVisitor annotation = clazz.visitAnnotation(annotationType.getDescriptor(), true);650Type structureType = Type.getObjectType(getStructureClassName());651652annotation.visit("structureClass", structureType);653annotation.visitEnd();654}655656private void doConstructors(String superClassName) {657final String abstractPointerFromLong = Type.getMethodDescriptor(abstractPointerType, Type.LONG_TYPE);658final String abstractPointerFromScalar = Type.getMethodDescriptor(abstractPointerType, scalarType);659final String classFromLong = Type.getMethodDescriptor(classType, Type.LONG_TYPE);660final String classFromScalar = Type.getMethodDescriptor(classType, scalarType);661MethodVisitor method;662663// protected SELF(long address) { super(address); }664{665method = clazz.visitMethod(ACC_PROTECTED, "<init>", voidFromLong, null, null);666667method.visitCode();668method.visitVarInsn(ALOAD, 0);669method.visitVarInsn(LLOAD, 1);670method.visitMethodInsn(INVOKESPECIAL, superClassName, "<init>", voidFromLong, false);671method.visitInsn(RETURN);672method.visitMaxs(3, 3);673method.visitEnd();674}675676// public static SELF cast(long address) { if (address == 0) return NULL; return new SELF(address); }677{678method = clazz.visitMethod(ACC_PUBLIC | ACC_STATIC, "cast", classFromLong, null, null);679680Label nonNull = new Label();681682method.visitCode();683method.visitVarInsn(LLOAD, 0);684method.visitInsn(LCONST_0);685method.visitInsn(LCMP);686method.visitJumpInsn(IFNE, nonNull);687method.visitFieldInsn(GETSTATIC, className, "NULL", classType.getDescriptor());688method.visitInsn(ARETURN);689690method.visitLabel(nonNull);691method.visitFrame(F_SAME, 0, null, 0, null);692method.visitTypeInsn(NEW, className);693method.visitInsn(DUP);694method.visitVarInsn(LLOAD, 0);695method.visitMethodInsn(INVOKESPECIAL, className, "<init>", voidFromLong, false);696method.visitInsn(ARETURN);697698method.visitMaxs(4, 2);699method.visitEnd();700}701702// public static SELF cast(AbstractPointer structure) { return cast(structure.getAddress()); }703{704method = clazz.visitMethod(ACC_PUBLIC | ACC_STATIC, "cast",705Type.getMethodDescriptor(classType, abstractPointerType), null, null);706707method.visitCode();708method.visitVarInsn(ALOAD, 0);709method.visitMethodInsn(INVOKEVIRTUAL, abstractPointerType.getInternalName(), "getAddress", longFromVoid,710false);711method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);712method.visitInsn(ARETURN);713method.visitMaxs(2, 1);714method.visitEnd();715}716717// public static SELF cast(UDATA udata) { return cast(udata.longValue()); }718{719method = clazz.visitMethod(ACC_PUBLIC | ACC_STATIC, "cast", Type.getMethodDescriptor(classType, udataType),720null, null);721722method.visitCode();723method.visitVarInsn(ALOAD, 0);724method.visitMethodInsn(INVOKEVIRTUAL, udataType.getInternalName(), "longValue", longFromVoid, false);725method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);726method.visitInsn(ARETURN);727method.visitMaxs(2, 1);728method.visitEnd();729}730731// public SELF add(long count) { return addOffset(count * BASE.SIZEOF); }732{733method = clazz.visitMethod(ACC_PUBLIC, "add", classFromLong, null, null);734735method.visitCode();736method.visitVarInsn(ALOAD, 0);737method.visitVarInsn(LLOAD, 1);738loadLong(method, structure.getSizeOf());739method.visitInsn(LMUL);740method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromLong, false);741method.visitInsn(ARETURN);742method.visitMaxs(5, 3);743method.visitEnd();744745// bridge: AbstractPointer add(long count)746method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "add", abstractPointerFromLong, null, null);747748method.visitCode();749method.visitVarInsn(ALOAD, 0);750method.visitVarInsn(LLOAD, 1);751method.visitMethodInsn(INVOKEVIRTUAL, className, "add", classFromLong, false);752method.visitInsn(ARETURN);753method.visitMaxs(3, 3);754method.visitEnd();755}756757// public SELF add(Scalar count) { return add(count.longValue()); }758{759method = clazz.visitMethod(ACC_PUBLIC, "add", classFromScalar, null, null);760761method.visitCode();762method.visitVarInsn(ALOAD, 0);763method.visitVarInsn(ALOAD, 1);764method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);765method.visitMethodInsn(INVOKEVIRTUAL, className, "add", classFromLong, false);766method.visitInsn(ARETURN);767method.visitMaxs(3, 2);768method.visitEnd();769770// bridge: AbstractPointer add(Scalar count)771method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "add", abstractPointerFromScalar, null, null);772773method.visitCode();774method.visitVarInsn(ALOAD, 0);775method.visitVarInsn(ALOAD, 1);776method.visitMethodInsn(INVOKEVIRTUAL, className, "add", classFromScalar, false);777method.visitInsn(ARETURN);778method.visitMaxs(2, 2);779method.visitEnd();780}781782// public SELF addOffset(long offset) { return cast(address + offset); }783{784method = clazz.visitMethod(ACC_PUBLIC, "addOffset", classFromLong, null, null);785786method.visitCode();787method.visitVarInsn(ALOAD, 0);788method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());789method.visitVarInsn(LLOAD, 1);790method.visitInsn(LADD);791method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);792method.visitInsn(ARETURN);793method.visitMaxs(4, 3);794method.visitEnd();795796// bridge: AbstractPointer addOffset(long offset)797method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "addOffset", abstractPointerFromLong, null, null);798799method.visitCode();800method.visitVarInsn(ALOAD, 0);801method.visitVarInsn(LLOAD, 1);802method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromLong, false);803method.visitInsn(ARETURN);804method.visitMaxs(3, 3);805method.visitEnd();806}807808// public SELF addOffset(Scalar offset) { return addOffset(offset.longValue()); }809{810method = clazz.visitMethod(ACC_PUBLIC, "addOffset", classFromScalar, null, null);811812method.visitCode();813method.visitVarInsn(ALOAD, 0);814method.visitVarInsn(ALOAD, 1);815method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);816method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromLong, false);817method.visitInsn(ARETURN);818method.visitMaxs(3, 2);819method.visitEnd();820821// bridge: AbstractPointer addOffset(Scalar offset)822method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "addOffset", abstractPointerFromScalar, null, null);823824method.visitCode();825method.visitVarInsn(ALOAD, 0);826method.visitVarInsn(ALOAD, 1);827method.visitMethodInsn(INVOKEVIRTUAL, className, "addOffset", classFromScalar, false);828method.visitInsn(ARETURN);829method.visitMaxs(2, 2);830method.visitEnd();831}832833// public SELF sub(long count) { return subOffset(count * SIZEOF); }834{835method = clazz.visitMethod(ACC_PUBLIC, "sub", classFromLong, null, null);836837method.visitCode();838method.visitVarInsn(ALOAD, 0);839method.visitVarInsn(LLOAD, 1);840loadLong(method, structure.getSizeOf());841method.visitInsn(LMUL);842method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromLong, false);843method.visitInsn(ARETURN);844method.visitMaxs(5, 3);845method.visitEnd();846847// bridge: AbstractPointer sub(long count)848method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "sub", abstractPointerFromLong, null, null);849850method.visitCode();851method.visitVarInsn(ALOAD, 0);852method.visitVarInsn(LLOAD, 1);853method.visitMethodInsn(INVOKEVIRTUAL, className, "sub", classFromLong, false);854method.visitInsn(ARETURN);855method.visitMaxs(3, 3);856method.visitEnd();857}858859// public SELF sub(Scalar count) { return sub(count.longValue()); }860{861method = clazz.visitMethod(ACC_PUBLIC, "sub", classFromScalar, null, null);862863method.visitCode();864method.visitVarInsn(ALOAD, 0);865method.visitVarInsn(ALOAD, 1);866method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);867method.visitMethodInsn(INVOKEVIRTUAL, className, "sub", classFromLong, false);868method.visitInsn(ARETURN);869method.visitMaxs(3, 2);870method.visitEnd();871872// bridge: AbstractPointer sub(Scalar count)873method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "sub", abstractPointerFromScalar, null, null);874875method.visitCode();876method.visitVarInsn(ALOAD, 0);877method.visitVarInsn(ALOAD, 1);878method.visitMethodInsn(INVOKEVIRTUAL, className, "sub", classFromScalar, false);879method.visitInsn(ARETURN);880method.visitMaxs(2, 2);881method.visitEnd();882}883884// public SELF subOffset(long offset) { return cast(address - offset); }885{886method = clazz.visitMethod(ACC_PUBLIC, "subOffset", classFromLong, null, null);887888method.visitCode();889method.visitVarInsn(ALOAD, 0);890method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());891method.visitVarInsn(LLOAD, 1);892method.visitInsn(LSUB);893method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);894method.visitInsn(ARETURN);895method.visitMaxs(5, 3);896method.visitEnd();897898// bridge: AbstractPointer subOffset(long offset)899method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "subOffset", abstractPointerFromLong, null, null);900901method.visitCode();902method.visitVarInsn(ALOAD, 0);903method.visitVarInsn(LLOAD, 1);904method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromLong, false);905method.visitInsn(ARETURN);906method.visitMaxs(3, 3);907method.visitEnd();908}909910// public SELF subOffset(Scalar offset) { return subOffset(offset.longValue()); }911{912method = clazz.visitMethod(ACC_PUBLIC, "subOffset", classFromScalar, null, null);913914method.visitCode();915method.visitVarInsn(ALOAD, 0);916method.visitVarInsn(ALOAD, 1);917method.visitMethodInsn(INVOKEVIRTUAL, scalarType.getInternalName(), "longValue", longFromVoid, false);918method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromLong, false);919method.visitInsn(ARETURN);920method.visitMaxs(3, 2);921method.visitEnd();922923// bridge: AbstractPointer subOffset(Scalar offset)924method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "subOffset", abstractPointerFromScalar, null, null);925926method.visitCode();927method.visitVarInsn(ALOAD, 0);928method.visitVarInsn(ALOAD, 1);929method.visitMethodInsn(INVOKEVIRTUAL, className, "subOffset", classFromScalar, false);930method.visitInsn(ARETURN);931method.visitMaxs(2, 2);932method.visitEnd();933}934935// public SELF untag(long mask) { return cast(address & ~mask); }936{937method = clazz.visitMethod(ACC_PUBLIC, "untag", classFromLong, null, null);938939method.visitCode();940method.visitVarInsn(ALOAD, 0);941method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());942method.visitVarInsn(LLOAD, 1);943loadLong(method, -1);944method.visitInsn(LXOR);945method.visitInsn(LAND);946947method.visitMethodInsn(INVOKESTATIC, className, "cast", classFromLong, false);948method.visitInsn(ARETURN);949method.visitMaxs(6, 3);950method.visitEnd();951952// bridge: AbstractPointer untag(long tagBits)953method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "untag", abstractPointerFromLong, null, null);954955method.visitCode();956method.visitVarInsn(ALOAD, 0);957method.visitVarInsn(LLOAD, 1);958method.visitMethodInsn(INVOKEVIRTUAL, className, "untag", classFromLong, false);959method.visitInsn(ARETURN);960method.visitMaxs(3, 3);961method.visitEnd();962}963964// public SELF untag() { return untag(UDATA.SIZEOF - 1); }965{966String classFromVoid = Type.getMethodDescriptor(classType);967968method = clazz.visitMethod(ACC_PUBLIC, "untag", classFromVoid, null, null);969970method.visitCode();971method.visitVarInsn(ALOAD, 0);972loadLong(method, reader.getSizeOfUDATA() - 1);973method.visitMethodInsn(INVOKEVIRTUAL, className, "untag", classFromLong, false);974method.visitInsn(ARETURN);975method.visitMaxs(3, 1);976method.visitEnd();977978// bridge: AbstractPointer untag()979method = clazz.visitMethod(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, "untag", Type.getMethodDescriptor(abstractPointerType), null, null);980981method.visitCode();982method.visitVarInsn(ALOAD, 0);983method.visitMethodInsn(INVOKEVIRTUAL, className, "untag", classFromVoid, false);984method.visitInsn(ARETURN);985method.visitMaxs(1, 1);986method.visitEnd();987}988989// protected long sizeOfBaseType() { return BASE.SIZEOF; }990{991method = clazz.visitMethod(ACC_PROTECTED, "sizeOfBaseType", longFromVoid, null, null);992993method.visitCode();994loadLong(method, structure.getSizeOf());995method.visitInsn(LRETURN);996method.visitMaxs(2, 1);997method.visitEnd();998}999}10001001/* Sample generated code:1002*1003* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_fifteenMinuteAverageOffset_", declaredType="double")1004* public double fifteenMinuteAverage() throws CorruptDataException {1005* return getDoubleAtOffset(J9PortSysInfoLoadData._fifteenMinuteAverageOffset_);1006* }1007*/1008private void doDoubleMethod(FieldDescriptor field) {1009MethodVisitor method = beginAnnotatedMethod(field, field.getName(), doubleFromVoid);10101011method.visitCode();1012if (checkPresent(field, method)) {1013method.visitVarInsn(ALOAD, 0);1014loadLong(method, field.getOffset());1015method.visitMethodInsn(INVOKEVIRTUAL, className, "getDoubleAtOffset", doubleFromLong, false);1016method.visitInsn(DRETURN);1017}1018method.visitMaxs(3, 1);1019method.visitEnd();10201021doEAMethod("Double", field);1022}10231024/* Sample generated code:1025*1026* public UDATAPointer castClassCacheEA() throws CorruptDataException {1027* return UDATAPointer.cast(nonNullFieldEA(J9Class._castClassCacheOffset_));1028* }1029*/1030private void doEAMethod(String actualType, FieldDescriptor field) {1031String accessorName = field.getName() + "EA";1032String returnType = generalizeSimpleType(actualType);1033String qualifiedReturnType = qualifyPointerType(returnType);1034String qualifiedActualType = qualifyPointerType(actualType);10351036String returnDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedReturnType));1037String actualDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedActualType), Type.LONG_TYPE);10381039MethodVisitor method = beginMethod(field, accessorName, returnDesc);10401041method.visitCode();1042if (checkPresent(field, method)) {1043method.visitVarInsn(ALOAD, 0);1044loadLong(method, field.getOffset());1045method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);1046method.visitMethodInsn(INVOKESTATIC, qualifiedActualType, "cast", actualDesc, false);1047method.visitInsn(ARETURN);1048}1049method.visitMaxs(3, 1);1050method.visitEnd();1051}10521053/* Sample generated code:1054*1055* public EnumPointer _buildResultEA() throws CorruptDataException {1056* return EnumPointer.cast(nonNullFieldEA(ClassFileWriter.__buildResultOffset_, BuildResult.class));1057* }1058*/1059private void doEnumEAMethod(FieldDescriptor field) {1060String accessorName = field.getName() + "EA";1061String enumPointerDesc = qualifyPointerType("Enum");1062Type enumPointerType = Type.getObjectType(enumPointerDesc);1063String returnDesc = Type.getMethodDescriptor(enumPointerType);1064String castDesc = Type.getMethodDescriptor(enumPointerType, Type.LONG_TYPE, Type.getType(Class.class));1065Type enumType = Type.getObjectType(qualifyType(getEnumType(field.getType())));10661067MethodVisitor method = beginMethod(field, accessorName, returnDesc);10681069method.visitCode();1070if (checkPresent(field, method)) {1071method.visitVarInsn(ALOAD, 0);1072loadLong(method, field.getOffset());1073method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);1074method.visitLdcInsn(enumType);1075method.visitMethodInsn(INVOKESTATIC, enumPointerDesc, "cast", castDesc, false);1076method.visitInsn(ARETURN);1077}1078method.visitMaxs(3, 1);1079method.visitEnd();1080}10811082/* Sample generated code:1083*1084* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_physicalProcessorOffset_", declaredType="J9ProcessorArchitecture")1085* public long physicalProcessor() throws CorruptDataException {1086* return getIntAtOffset(J9ProcessorDesc._physicalProcessorOffset_);1087* }1088*1089* If the size of the field type is not 4, getByteAtOffset, getShortAtOffset1090* or getLongAtOffset is used as appropriate.1091*/1092private void doEnumMethod(FieldDescriptor field) {1093String enumType = getEnumType(field.getType());1094int enumSize = reader.getStructureSizeOf(enumType);1095PrimitiveAccessor accessor = PrimitiveAccessor.forSize(enumSize);10961097MethodVisitor method = beginAnnotatedMethod(field, field.getName(), longFromVoid);10981099method.visitCode();1100if (checkPresent(field, method)) {1101method.visitVarInsn(ALOAD, 0);1102loadLong(method, field.getOffset());1103method.visitMethodInsn(INVOKEVIRTUAL, className, accessor.methodName, accessor.descriptor, false);1104if (!accessor.returnsLong) {1105method.visitInsn(I2L);1106}1107method.visitInsn(LRETURN);1108}1109method.visitMaxs(3, 1);1110method.visitEnd();11111112doEnumEAMethod(field);1113}11141115/* Sample generated code:1116*1117* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="__resultOffset_", declaredType="BuildResult*")1118* public EnumPointer _result() throws CorruptDataException {1119* return EnumPointer.cast(getPointerAtOffset(ROMClassVerbosePhase.__resultOffset_), BuildResult.class);1120* }1121*/1122private void doEnumPointerMethod(FieldDescriptor field) {1123String enumPointerDesc = qualifyPointerType("Enum");1124Type enumPointerType = Type.getObjectType(enumPointerDesc);1125String returnDesc = Type.getMethodDescriptor(enumPointerType);1126String castDesc = Type.getMethodDescriptor(enumPointerType, Type.LONG_TYPE, Type.getType(Class.class));1127String targetType = getTargetType(getEnumType(field.getType()));1128Type enumType = Type.getObjectType(qualifyType(targetType));11291130MethodVisitor method = beginMethod(field, field.getName(), returnDesc);11311132method.visitCode();1133if (checkPresent(field, method)) {1134method.visitVarInsn(ALOAD, 0);1135loadLong(method, field.getOffset());1136method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1137method.visitLdcInsn(enumType);1138method.visitMethodInsn(INVOKESTATIC, enumPointerDesc, "cast", castDesc, false);1139method.visitInsn(ARETURN);1140}1141method.visitMaxs(3, 2);1142method.visitEnd();11431144doEAMethod("Pointer", field);1145}11461147/* Sample generated code:1148*1149* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_refOffset_", declaredType="fj9object_t")1150* public J9ObjectPointer ref() throws CorruptDataException {1151* return getObjectReferenceAtOffset(Example._refOffset_);1152* }1153*/1154private void doFJ9ObjectMethod(FieldDescriptor field) {1155Type objectType = Type.getObjectType(qualifyPointerType("J9Object"));1156String returnDesc = Type.getMethodDescriptor(objectType);1157String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);11581159MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);11601161method.visitCode();1162if (checkPresent(field, method)) {1163method.visitVarInsn(ALOAD, 0);1164loadLong(method, field.getOffset());1165method.visitMethodInsn(INVOKEVIRTUAL, className, "getObjectReferenceAtOffset", accessorDesc, false);1166method.visitInsn(ARETURN);1167}1168method.visitMaxs(3, 1);1169method.visitEnd();11701171doEAMethod("ObjectReference", field);1172}11731174/* Sample generated code:1175*1176* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_fieldAddressOffset_", declaredType="const fj9object_t*")1177* public ObjectReferencePointer fieldAddress() throws CorruptDataException {1178* return ObjectReferencePointer.cast(getPointerAtOffset(J9MM_IterateObjectRefDescriptor._fieldAddressOffset_));1179* }1180*/1181private void doFJ9ObjectPointerMethod(FieldDescriptor field) {1182String returnType = qualifyPointerType("ObjectReference");1183Type objectType = Type.getObjectType(returnType);1184String returnDesc = Type.getMethodDescriptor(objectType);1185String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);11861187MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);11881189method.visitCode();1190if (checkPresent(field, method)) {1191method.visitVarInsn(ALOAD, 0);1192loadLong(method, field.getOffset());1193method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1194method.visitMethodInsn(INVOKESTATIC, returnType, "cast", castDesc, false);1195method.visitInsn(ARETURN);1196}1197method.visitMaxs(3, 1);1198method.visitEnd();11991200doEAMethod("Pointer", field);1201}12021203/* Sample generated code:1204*1205* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_fOffset_", declaredType="jfloat")1206* public float f() throws CorruptDataException {1207* return getFloatAtOffset(jvalue._fOffset_);1208* }1209*/1210private void doFloatMethod(FieldDescriptor field) {1211MethodVisitor method = beginAnnotatedMethod(field, field.getName(), floatFromVoid);12121213method.visitCode();1214if (checkPresent(field, method)) {1215method.visitVarInsn(ALOAD, 0);1216loadLong(method, field.getOffset());1217method.visitMethodInsn(INVOKEVIRTUAL, className, "getFloatAtOffset", floatFromLong, false);1218method.visitInsn(FRETURN);1219}1220method.visitMaxs(3, 1);1221method.visitEnd();12221223doEAMethod("Float", field);1224}12251226/* Sample generated code:1227*1228* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_clazzOffset_", declaredType="j9objectclass_t")1229* public J9ClassPointer clazz() throws CorruptDataException {1230* return getObjectClassAtOffset(J9Object._clazzOffset_);1231* }1232*/1233private void doJ9ObjectClassMethod(FieldDescriptor field) {1234String returnType = qualifyPointerType("J9Class");1235Type objectType = Type.getObjectType(returnType);1236String returnDesc = Type.getMethodDescriptor(objectType);1237String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);12381239MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);12401241method.visitCode();1242if (checkPresent(field, method)) {1243method.visitVarInsn(ALOAD, 0);1244loadLong(method, field.getOffset());1245method.visitMethodInsn(INVOKEVIRTUAL, className, "getObjectClassAtOffset", accessorDesc, false);1246method.visitInsn(ARETURN);1247}1248method.visitMaxs(3, 1);1249method.visitEnd();12501251doEAMethod("ObjectClassReference", field);1252}12531254/* Sample generated code:1255*1256* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_classPtrOffset_", declaredType="j9objectclass_t*")1257* public ObjectClassReferencePointer classPtr() throws CorruptDataException {1258* return ObjectClassReferencePointer.cast(getPointerAtOffset(Example._classPtrOffset_));1259* }1260*/1261private void doJ9ObjectClassPointerMethod(FieldDescriptor field) {1262String returnType = qualifyPointerType("ObjectClassReference");1263Type objectType = Type.getObjectType(returnType);1264String returnDesc = Type.getMethodDescriptor(objectType);1265String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);12661267MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);12681269method.visitCode();1270if (checkPresent(field, method)) {1271method.visitVarInsn(ALOAD, 0);1272loadLong(method, field.getOffset());1273method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1274method.visitMethodInsn(INVOKESTATIC, returnType, "cast", accessorDesc, false);1275method.visitInsn(ARETURN);1276}1277method.visitMaxs(3, 1);1278method.visitEnd();12791280doEAMethod("Pointer", field);1281}12821283/* Sample generated code:1284*1285* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_monitorOffset_", declaredType="j9objectmonitor_t")1286* public J9ObjectMonitorPointer monitor() throws CorruptDataException {1287* return getObjectMonitorAtOffset(Example._monitorOffset_);1288* }1289*/1290private void doJ9ObjectMonitorMethod(FieldDescriptor field) {1291String returnType = qualifyPointerType("J9ObjectMonitor");1292Type objectType = Type.getObjectType(returnType);1293String returnDesc = Type.getMethodDescriptor(objectType);1294String accessorDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);12951296MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);12971298method.visitCode();1299if (checkPresent(field, method)) {1300method.visitVarInsn(ALOAD, 0);1301loadLong(method, field.getOffset());1302method.visitMethodInsn(INVOKEVIRTUAL, className, "getObjectMonitorAtOffset", accessorDesc, false);1303method.visitInsn(ARETURN);1304}1305method.visitMaxs(3, 1);1306method.visitEnd();13071308doEAMethod("ObjectMonitorReference", field);1309}13101311/* Sample generated code:1312*1313* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_lockwordOffset_", declaredType="j9objectmonitor_t*")1314* public ObjectMonitorReferencePointer lockword() throws CorruptDataException {1315* return ObjectMonitorReferencePointer.cast(getPointerAtOffset(Example._lockwordOffset_));1316* }1317*/1318private void doJ9ObjectMonitorPointerMethod(FieldDescriptor field) {1319String returnType = qualifyPointerType("ObjectMonitorReference");1320Type objectType = Type.getObjectType(returnType);1321String returnDesc = Type.getMethodDescriptor(objectType);1322String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);13231324MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);13251326method.visitCode();1327if (checkPresent(field, method)) {1328method.visitVarInsn(ALOAD, 0);1329loadLong(method, field.getOffset());1330method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1331method.visitMethodInsn(INVOKESTATIC, returnType, "cast", castDesc, false);1332method.visitInsn(ARETURN);1333}1334method.visitMaxs(3, 1);1335method.visitEnd();13361337doEAMethod("Pointer", field);1338}13391340private void doNullInstance() {1341// public static final SELF NULL = new SELF(0);1342clazz.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, "NULL", classType.getDescriptor(), null, null).visitEnd();13431344MethodVisitor clinit = clazz.visitMethod(ACC_STATIC, "<clinit>", voidMethod, null, null);13451346clinit.visitCode();1347clinit.visitTypeInsn(NEW, className);1348clinit.visitInsn(DUP);1349clinit.visitInsn(LCONST_0);1350clinit.visitMethodInsn(INVOKESPECIAL, className, "<init>", voidFromLong, false);1351clinit.visitFieldInsn(PUTSTATIC, className, "NULL", classType.getDescriptor());1352clinit.visitInsn(RETURN);1353clinit.visitMaxs(4, 0);1354clinit.visitEnd();1355}13561357/* Sample generated code:1358*1359* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_ramConstantPoolOffset_", declaredType="UDATA*")1360* public UDATAPointer ramConstantPool() throws CorruptDataException {1361* return UDATAPointer.cast(getPointerAtOffset(J9Class._ramConstantPoolOffset_));1362* }1363*/1364private void doPointerMethod(FieldDescriptor field) {1365String targetType = getTargetType(removeTypeTags(field.getType()));1366String qualifiedTargetType = qualifyPointerType(targetType);1367String castDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedTargetType), Type.LONG_TYPE);13681369String returnType = generalizeSimpleType(targetType);1370String qualifiedReturnType = qualifyPointerType(returnType);1371String returnDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedReturnType));13721373MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);13741375method.visitCode();1376if (checkPresent(field, method)) {1377method.visitVarInsn(ALOAD, 0);1378loadLong(method, field.getOffset());1379method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1380method.visitMethodInsn(INVOKESTATIC, qualifiedTargetType, "cast", castDesc, false);1381method.visitInsn(ARETURN);1382}1383method.visitMaxs(3, 1);1384method.visitEnd();13851386doEAMethod("Pointer", field);1387}13881389/* Sample generated code:1390*1391* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_castClassCacheOffset_", declaredType="UDATA")1392* public UDATA castClassCache() throws CorruptDataException {1393* return new UDATA(getLongAtOffset(J9Class._castClassCacheOffset_));1394* }1395*/1396private void doSimpleTypeMethod(FieldDescriptor field, int type) {1397String fieldType = field.getType();1398String returnType = generalizeSimpleType(fieldType);1399String qualifiedFieldType = qualifyType(fieldType);1400String qualifiedReturnType = qualifyType(returnType);1401PrimitiveAccessor accessor = simpleTypeAccessor(type);1402String returnDesc = Type.getMethodDescriptor(Type.getObjectType(qualifiedReturnType));14031404MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);14051406method.visitCode();1407if (checkPresent(field, method)) {1408method.visitTypeInsn(NEW, qualifiedFieldType);1409method.visitInsn(DUP);1410method.visitVarInsn(ALOAD, 0);1411loadLong(method, field.getOffset());1412method.visitMethodInsn(INVOKEVIRTUAL, className, accessor.methodName, accessor.descriptor, false);1413if (!accessor.returnsLong) {1414method.visitInsn(I2L);1415}1416method.visitMethodInsn(INVOKESPECIAL, qualifiedFieldType, "<init>", voidFromLong, false);1417method.visitInsn(ARETURN);1418}1419method.visitMaxs(5, 1);1420method.visitEnd();14211422doEAMethod(fieldType, field);1423}14241425/* Sample generated code:1426*1427* public WideSelfRelativePointer puddleListEA() throws CorruptDataException {1428* return WideSelfRelativePointer.cast(nonNullFieldEA(J9Pool._puddleListOffset_));1429* }1430*/1431private void doSRPEAMethod(FieldDescriptor field, boolean isWide) {1432String accessorName = field.getName() + "EA";1433String returnTypeName = qualifyPointerType(isWide ? "WideSelfRelative" : "SelfRelative");1434Type returnType = Type.getObjectType(returnTypeName);1435String returnDesc = Type.getMethodDescriptor(returnType);1436String castDesc = Type.getMethodDescriptor(returnType, Type.LONG_TYPE);14371438MethodVisitor method = beginMethod(field, accessorName, returnDesc);14391440method.visitCode();1441if (checkPresent(field, method)) {1442method.visitVarInsn(ALOAD, 0);1443loadLong(method, field.getOffset());1444method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);1445method.visitMethodInsn(INVOKESTATIC, returnTypeName, "cast", castDesc, false);1446method.visitInsn(ARETURN);1447}1448method.visitMaxs(3, 1);1449method.visitEnd();1450}14511452/* Sample generated code:1453*1454* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_annotationDataOffset_", declaredType="J9SRP(UDATA)")1455* public UDATAPointer annotationData() throws CorruptDataException {1456* int srp = getIntAtOffset(J9AnnotationInfoEntry._annotationDataOffset_);1457* if (srp == 0) {1458* return UDATAPointer.NULL;1459* }1460* return UDATAPointer.cast(address + J9AnnotationInfoEntry._annotationDataOffset_ + srp);1461* }1462*/1463private void doSRPMethod(FieldDescriptor field, boolean isWide) {1464final String prefix = isWide ? "J9WSRP" : "J9SRP";1465final int prefixLength = prefix.length();1466final String rawFieldType = field.getType();1467String targetType;14681469if (rawFieldType.startsWith(prefix) && rawFieldType.startsWith("(", prefixLength)) {1470targetType = rawFieldType.substring(prefixLength + 1, rawFieldType.length() - 1).trim();1471} else {1472targetType = "void";1473}14741475int type = typeManager.getType(targetType);14761477switch (type) {1478case StructureTypeManager.TYPE_J9SRP:1479targetType = "SelfRelative";1480break;1481case StructureTypeManager.TYPE_J9WSRP:1482targetType = "WideSelfRelative";1483break;1484case StructureTypeManager.TYPE_STRUCTURE:1485targetType = removeTypeTags(targetType);1486break;1487case StructureTypeManager.TYPE_VOID:1488targetType = "Void";1489break;1490default:1491if ((StructureTypeManager.TYPE_SIMPLE_MIN <= type) && (type <= StructureTypeManager.TYPE_SIMPLE_MAX)) {1492targetType = removeTypeTags(targetType);1493} else {1494throw new IllegalArgumentException("Unexpected SRP type: " + rawFieldType);1495}1496break;1497}14981499String returnTypeName = qualifyPointerType(generalizeSimpleType(targetType));1500Type returnType = Type.getObjectType(returnTypeName);1501String returnDesc = Type.getMethodDescriptor(returnType);1502String qualifiedPointerName = qualifyPointerType(targetType);1503String qualifiedPointerDesc = Type.getObjectType(qualifiedPointerName).getDescriptor();15041505MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);15061507method.visitCode();1508if (checkPresent(field, method)) {1509Label nonNull = new Label();15101511method.visitVarInsn(ALOAD, 0);1512loadLong(method, field.getOffset());15131514if (isWide) {1515method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1516method.visitVarInsn(LSTORE, 1);15171518method.visitVarInsn(LLOAD, 1);1519method.visitInsn(LCONST_0);1520method.visitInsn(LCMP);1521} else {1522method.visitMethodInsn(INVOKEVIRTUAL, className, "getIntAtOffset", intFromLong, false);1523method.visitVarInsn(ISTORE, 1);15241525method.visitVarInsn(ILOAD, 1);1526}1527method.visitJumpInsn(IFNE, nonNull);15281529method.visitFieldInsn(GETSTATIC, qualifiedPointerName, "NULL", qualifiedPointerDesc);1530method.visitInsn(ARETURN);15311532method.visitLabel(nonNull);1533method.visitFrame(F_APPEND, 1, new Object[] { isWide ? LONG : INTEGER }, 0, null);1534method.visitVarInsn(ALOAD, 0);1535method.visitFieldInsn(GETFIELD, className, "address", Type.LONG_TYPE.getDescriptor());1536addLong(method, field.getOffset());1537if (isWide) {1538method.visitVarInsn(LLOAD, 1);1539} else {1540method.visitVarInsn(ILOAD, 1);1541method.visitInsn(I2L);1542}1543method.visitInsn(LADD);15441545String castDesc = Type.getMethodDescriptor(returnType, Type.LONG_TYPE);15461547method.visitMethodInsn(INVOKESTATIC, qualifiedPointerName, "cast", castDesc, false);1548method.visitInsn(ARETURN);1549}1550method.visitMaxs(4, isWide ? 3 : 2);1551method.visitEnd();15521553doSRPEAMethod(field, isWide);1554}15551556/* Sample generated code:1557*1558* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_sharedHeadNodePtrOffset_", declaredType="J9SRP*")1559* public SelfRelativePointer sharedHeadNodePtr() throws CorruptDataException {1560* return SelfRelativePointer.cast(getPointerAtOffset(J9SharedInvariantInternTable._sharedHeadNodePtrOffset_));1561* }1562*/1563private void doSRPPointerMethod(FieldDescriptor field, boolean wide) {1564String returnType = qualifyPointerType(wide ? "WideSelfRelative" : "SelfRelative");1565Type objectType = Type.getObjectType(returnType);1566String returnDesc = Type.getMethodDescriptor(objectType);1567String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);15681569MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);15701571method.visitCode();1572if (checkPresent(field, method)) {1573method.visitVarInsn(ALOAD, 0);1574loadLong(method, field.getOffset());1575method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1576method.visitMethodInsn(INVOKESTATIC, returnType, "cast", castDesc, false);1577method.visitInsn(ARETURN);1578}1579method.visitMaxs(3, 1);1580method.visitEnd();15811582doEAMethod("Pointer", field);1583}15841585/* Sample generated code:1586*1587* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_permOffset_", declaredType="J9Permission")1588* public J9PermissionPointer perm() throws CorruptDataException {1589* return J9PermissionPointer.cast(nonNullFieldEA(J9FileStat._permOffset_));1590* }1591*/1592private void doStructureMethod(FieldDescriptor field) {1593String fieldType = removeTypeTags(field.getType());1594String returnType = "void".equals(fieldType) ? "Void" : fieldType;1595String qualifiedReturnType = qualifyPointerType(returnType);1596Type objectType = Type.getObjectType(qualifiedReturnType);1597String returnDesc = Type.getMethodDescriptor(objectType);1598String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);15991600MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);16011602method.visitCode();1603if (checkPresent(field, method)) {1604method.visitVarInsn(ALOAD, 0);1605loadLong(method, field.getOffset());1606method.visitMethodInsn(INVOKEVIRTUAL, className, "nonNullFieldEA", longFromLong, false);1607method.visitMethodInsn(INVOKESTATIC, qualifiedReturnType, "cast", castDesc, false);1608method.visitInsn(ARETURN);1609}1610method.visitMaxs(3, 1);1611method.visitEnd();16121613doEAMethod("Pointer", field);1614}16151616/* Sample generated code:1617*1618* @com.ibm.j9ddr.GeneratedFieldAccessor(offsetFieldName="_hostClassOffset_", declaredType="J9Class*")1619* public J9ClassPointer hostClass() throws CorruptDataException {1620* return J9ClassPointer.cast(getPointerAtOffset(J9Class._hostClassOffset_));1621* }1622*/1623private void doStructurePointerMethod(FieldDescriptor field) {1624String returnType = getTargetType(removeTypeTags(field.getType()));1625String qualifiedReturnType = qualifyPointerType(returnType);1626Type objectType = Type.getObjectType(qualifiedReturnType);1627String returnDesc = Type.getMethodDescriptor(objectType);1628String castDesc = Type.getMethodDescriptor(objectType, Type.LONG_TYPE);16291630MethodVisitor method = beginAnnotatedMethod(field, field.getName(), returnDesc);16311632method.visitCode();1633if (checkPresent(field, method)) {1634method.visitVarInsn(ALOAD, 0);1635loadLong(method, field.getOffset());1636method.visitMethodInsn(INVOKEVIRTUAL, className, "getPointerAtOffset", longFromLong, false);1637method.visitMethodInsn(INVOKESTATIC, qualifiedReturnType, "cast", castDesc, false);1638method.visitInsn(ARETURN);1639}1640method.visitMaxs(3, 1);1641method.visitEnd();16421643doEAMethod("Pointer", field);1644}16451646private byte[] generate() {1647String superClassName = structure.getSuperName();16481649if (superClassName.isEmpty()) {1650superClassName = basePrefix + "pointer/StructurePointer";1651} else {1652superClassName = basePrefix + "pointer/generated/" + superClassName + "Pointer";1653}16541655clazz.visit(V1_8, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, null);16561657doClassAnnotation();1658doNullInstance();1659doConstructors(superClassName);1660doAccessorMethods();16611662clazz.visitEnd();16631664return clazz.toByteArray();1665}16661667private String getStructureClassName() {1668return basePrefix + "structure/" + structure.getName();1669}16701671private String qualifyPointerType(String type) {1672String subPackage = predefinedPointerTypes.contains(type) ? "pointer/" : "pointer/generated/";16731674return basePrefix + subPackage + type + "Pointer";1675}16761677private String qualifyType(String type) {1678String subPackage = predefinedDataTypes.contains(type) ? "types/" : "structure/";16791680return basePrefix + subPackage + type;1681}16821683private PrimitiveAccessor simpleTypeAccessor(int type) {1684int size;16851686switch (type) {1687case StructureTypeManager.TYPE_I8:1688case StructureTypeManager.TYPE_U8:1689size = 1;1690break;1691case StructureTypeManager.TYPE_I16:1692case StructureTypeManager.TYPE_U16:1693size = 2;1694break;1695case StructureTypeManager.TYPE_I32:1696case StructureTypeManager.TYPE_U32:1697size = 4;1698break;1699case StructureTypeManager.TYPE_I64:1700case StructureTypeManager.TYPE_U64:1701size = 8;1702break;1703case StructureTypeManager.TYPE_IDATA:1704case StructureTypeManager.TYPE_UDATA:1705size = reader.getSizeOfUDATA();1706break;1707default:1708throw new IllegalArgumentException("type=" + type);1709}17101711return PrimitiveAccessor.forSize(size);1712}17131714}17151716enum PrimitiveAccessor {17171718BYTE("getByteAtOffset", HelperBase.byteFromLong, false),17191720INT("getIntAtOffset", HelperBase.intFromLong, false),17211722LONG("getLongAtOffset", HelperBase.longFromLong, true),17231724SHORT("getShortAtOffset", HelperBase.shortFromLong, false);17251726static PrimitiveAccessor forSize(int size) {1727switch (size) {1728case 1:1729return BYTE;1730case 2:1731return SHORT;1732case 4:1733return INT;1734case 8:1735return LONG;1736default:1737throw new IllegalArgumentException("size=" + size);1738}1739}17401741final String descriptor;17421743final String methodName;17441745final boolean returnsLong;17461747PrimitiveAccessor(String methodName, String descriptor, boolean returnsLong) {1748this.methodName = methodName;1749this.descriptor = descriptor;1750this.returnsLong = returnsLong;1751}17521753}17541755final class StructureHelper extends HelperBase {17561757static byte[] getClassBytes(StructureDescriptor structure, String className) {1758StructureHelper helper = new StructureHelper(structure, className);17591760return helper.generate();1761}17621763private final String className;17641765private final ClassWriter clazz;17661767private final MethodVisitor clinit;17681769private final StructureDescriptor structure;17701771private StructureHelper(StructureDescriptor structure, String className) {1772super();1773this.className = className;1774this.clazz = new ClassWriter(0);1775this.clazz.visit(V1_8, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, className, null, "java/lang/Object", null);1776this.clinit = clazz.visitMethod(ACC_STATIC, "<clinit>", voidMethod, null, null);1777this.clinit.visitCode();1778this.structure = structure;1779}17801781private void defineField(String name, Type type, long value) {1782String typeDescriptor = type.getDescriptor();17831784clazz.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, name, typeDescriptor, null, null).visitEnd();17851786if (type.getSort() == Type.INT) {1787loadInt(clinit, (int) value);1788} else {1789loadLong(clinit, value);1790}17911792clinit.visitFieldInsn(PUTSTATIC, className, name, typeDescriptor);1793}17941795private void defineFields() {1796defineField("SIZEOF", Type.LONG_TYPE, structure.getSizeOf());17971798// other constants1799for (ConstantDescriptor constant : structure.getConstants()) {1800defineField(constant.getName(), Type.LONG_TYPE, constant.getValue());1801}18021803// offsets1804int bitFieldBitCount = 0;1805for (FieldDescriptor field : structure.getFields()) {1806if (!field.isPresent()) {1807continue;1808}18091810String fieldName = field.getName();1811int fieldOffset = field.getOffset();1812String type = field.getType();1813int colonIndex = type.lastIndexOf(':');18141815// make sure match a bitfield, not a C++ namespace1816if (colonIndex <= 0 || type.charAt(colonIndex - 1) == ':') {1817// regular offset field1818defineField(String.format("_%sOffset_", fieldName), Type.INT_TYPE, fieldOffset);1819} else {1820// bitfield1821int bitSize = Integer.parseInt(type.substring(colonIndex + 1).trim());18221823/*1824* Newer blobs have accurate offsets of bitfields; adjust bitFieldBitCount1825* to account for any fields preceding this field. In older blobs the byte1826* offset of a bitfield is always zero, so this has no effect.1827*/1828bitFieldBitCount = Math.max(bitFieldBitCount, fieldOffset * Byte.SIZE);18291830if (bitSize > (StructureReader.BIT_FIELD_CELL_SIZE1831- (bitFieldBitCount % StructureReader.BIT_FIELD_CELL_SIZE))) {1832throw new InternalError(1833String.format("Bitfield %s->%s must not span cells", structure.getName(), fieldName));1834}18351836// 's' field1837defineField(String.format("_%s_s_", fieldName), Type.INT_TYPE, bitFieldBitCount);18381839// 'b' field1840defineField(String.format("_%s_b_", fieldName), Type.INT_TYPE, bitSize);18411842bitFieldBitCount += bitSize;1843}1844}18451846clinit.visitInsn(RETURN);1847clinit.visitMaxs(2, 0);1848clinit.visitEnd();1849}18501851private byte[] generate() {1852defineFields();18531854MethodVisitor method = clazz.visitMethod(ACC_PUBLIC, "<init>", voidMethod, null, null);18551856method.visitCode();1857method.visitVarInsn(ALOAD, 0);1858method.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", voidMethod, false);1859method.visitInsn(RETURN);1860method.visitMaxs(1, 1);1861method.visitEnd();18621863clazz.visitEnd();18641865return clazz.toByteArray();1866}18671868}186918701871