CompositeValueClass.java revision 12651:6ef01bd40ce2
1113287Sphk/* 2113287Sphk * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3113287Sphk * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4113287Sphk * 5113287Sphk * This code is free software; you can redistribute it and/or modify it 6113287Sphk * under the terms of the GNU General Public License version 2 only, as 7113287Sphk * published by the Free Software Foundation. 8113287Sphk * 9113287Sphk * This code is distributed in the hope that it will be useful, but WITHOUT 10113287Sphk * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11113287Sphk * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12113287Sphk * version 2 for more details (a copy is included in the LICENSE file that 13113287Sphk * accompanied this code). 14113287Sphk * 15113287Sphk * You should have received a copy of the GNU General Public License version 16113287Sphk * 2 along with this work; if not, write to the Free Software Foundation, 17113287Sphk * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18113287Sphk * 19113287Sphk * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20113287Sphk * or visit www.oracle.com if you need additional information or have any 21113287Sphk * questions. 22113287Sphk */ 23113287Sphkpackage org.graalvm.compiler.lir; 24113287Sphk 25113287Sphkimport java.lang.reflect.Field; 26113287Sphkimport java.util.Arrays; 27113287Sphkimport java.util.EnumSet; 28113287Sphk 29113287Sphkimport org.graalvm.compiler.core.common.FieldIntrospection; 30113287Sphkimport org.graalvm.compiler.core.common.Fields; 31140058Sruimport org.graalvm.compiler.core.common.FieldsScanner; 32113287Sphkimport org.graalvm.compiler.debug.GraalError; 33113287Sphkimport org.graalvm.compiler.lir.CompositeValue.Component; 34113287Sphkimport org.graalvm.compiler.lir.LIRInstruction.OperandFlag; 35113287Sphkimport org.graalvm.compiler.lir.LIRIntrospection.LIRFieldsScanner; 36113287Sphkimport org.graalvm.compiler.lir.LIRIntrospection.OperandModeAnnotation; 37113287Sphkimport org.graalvm.compiler.lir.LIRIntrospection.Values; 38113287Sphk 39140058Sru/** 40113287Sphk * Lazily associated metadata for every {@link CompositeValue} type. The metadata includes: 41113287Sphk * <ul> 42113287Sphk * <li>The offsets of fields annotated with {@link Component} as well as methods for iterating over 43113287Sphk * such fields.</li> 44115472Sru * </ul> 45115472Sru */ 46113287Sphkpublic final class CompositeValueClass<T> extends FieldIntrospection<T> { 47115472Sru 48115472Sru /** 49200968Smav * The CompositeValueClass is only used for formatting for the most part so cache it as a 50200968Smav * ClassValue. 51113287Sphk */ 52113287Sphk private static final ClassValue<CompositeValueClass<?>> compositeClass = new ClassValue<CompositeValueClass<?>>() { 53113287Sphk 54113287Sphk @Override 55113287Sphk protected CompositeValueClass<?> computeValue(Class<?> type) { 56113287Sphk CompositeValueClass<?> compositeValueClass = new CompositeValueClass<>(type); 57113287Sphk assert compositeValueClass.values.getDirectCount() == compositeValueClass.values.getCount() : "only direct fields are allowed in composites"; 58137456Ssos return compositeValueClass; 59137456Ssos } 60137456Ssos 61137456Ssos }; 62113287Sphk 63115472Sru @SuppressWarnings("unchecked") 64113287Sphk public static <T> CompositeValueClass<T> get(Class<T> type) { 65140442Sru return (CompositeValueClass<T>) compositeClass.get(type); 66140442Sru } 67140442Sru 68140442Sru private final Values values; 69140442Sru 70113287Sphk private CompositeValueClass(Class<T> clazz) { 71113287Sphk super(clazz); 72113287Sphk 73114916Sgordon CompositeValueFieldsScanner vfs = new CompositeValueFieldsScanner(new FieldsScanner.DefaultCalcOffset()); 74114916Sgordon vfs.scan(clazz, CompositeValue.class, false); 75 76 values = new Values(vfs.valueAnnotations.get(CompositeValue.Component.class)); 77 data = new Fields(vfs.data); 78 } 79 80 private static class CompositeValueFieldsScanner extends LIRFieldsScanner { 81 82 CompositeValueFieldsScanner(FieldsScanner.CalcOffset calc) { 83 super(calc); 84 valueAnnotations.put(CompositeValue.Component.class, new OperandModeAnnotation()); 85 } 86 87 @Override 88 protected EnumSet<OperandFlag> getFlags(Field field) { 89 EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class); 90 if (field.isAnnotationPresent(CompositeValue.Component.class)) { 91 result.addAll(Arrays.asList(field.getAnnotation(CompositeValue.Component.class).value())); 92 } else { 93 GraalError.shouldNotReachHere(); 94 } 95 return result; 96 } 97 } 98 99 @Override 100 public Fields[] getAllFields() { 101 return new Fields[]{data, values}; 102 } 103 104 @Override 105 public String toString() { 106 StringBuilder str = new StringBuilder(); 107 str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" components["); 108 values.appendFields(str); 109 str.append("] data["); 110 data.appendFields(str); 111 str.append("]"); 112 return str.toString(); 113 } 114 115 public static String format(CompositeValue obj) { 116 CompositeValueClass<?> valueClass = compositeClass.get(obj.getClass()); 117 StringBuilder result = new StringBuilder(); 118 119 LIRIntrospection.appendValues(result, obj, "", "", "{", "}", new String[]{""}, valueClass.values); 120 121 for (int i = 0; i < valueClass.data.getCount(); i++) { 122 result.append(" ").append(valueClass.data.getName(i)).append(": ").append(LIRIntrospection.getFieldString(obj, i, valueClass.data)); 123 } 124 125 return result.toString(); 126 } 127} 128