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