001/*
002 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.truffle;
024
025import jdk.internal.jvmci.meta.*;
026
027import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
028import com.oracle.truffle.api.nodes.Node.Child;
029import com.oracle.truffle.api.nodes.Node.Children;
030
031public class TruffleConstantReflectionProvider implements ConstantReflectionProvider {
032    private final ConstantReflectionProvider graalConstantReflection;
033    private final MetaAccessProvider metaAccess;
034
035    public TruffleConstantReflectionProvider(ConstantReflectionProvider graalConstantReflection, MetaAccessProvider metaAccess) {
036        this.graalConstantReflection = graalConstantReflection;
037        this.metaAccess = metaAccess;
038    }
039
040    public Boolean constantEquals(Constant x, Constant y) {
041        return graalConstantReflection.constantEquals(x, y);
042    }
043
044    public Integer readArrayLength(JavaConstant array) {
045        return graalConstantReflection.readArrayLength(array);
046    }
047
048    public JavaConstant readArrayElement(JavaConstant array, int index) {
049        return graalConstantReflection.readArrayElement(array, index);
050    }
051
052    public JavaConstant readConstantArrayElement(JavaConstant array, int index) {
053        return graalConstantReflection.readConstantArrayElement(array, index);
054    }
055
056    public JavaConstant readConstantArrayElementForOffset(JavaConstant array, long offset) {
057        return graalConstantReflection.readConstantArrayElementForOffset(array, offset);
058    }
059
060    public JavaConstant readConstantFieldValue(JavaField field0, JavaConstant receiver) {
061        ResolvedJavaField field = (ResolvedJavaField) field0;
062        if (!field.isStatic() && receiver.isNonNull()) {
063            JavaType fieldType = field.getType();
064            if (field.isFinal() || field.getAnnotation(CompilationFinal.class) != null ||
065                            (fieldType.getKind() == Kind.Object && (field.getAnnotation(Child.class) != null || field.getAnnotation(Children.class) != null))) {
066                final JavaConstant constant;
067                if (fieldType.getKind() == Kind.Object && fieldType instanceof ResolvedJavaType && ((ResolvedJavaType) fieldType).isArray() &&
068                                (field.getAnnotation(CompilationFinal.class) != null || field.getAnnotation(Children.class) != null)) {
069                    constant = graalConstantReflection.readStableFieldValue(field, receiver, true);
070                } else {
071                    constant = graalConstantReflection.readFieldValue(field, receiver);
072                }
073                assert verifyFieldValue(field, constant);
074                return constant;
075            }
076        } else if (field.isStatic()) {
077            if (field.getAnnotation(CompilationFinal.class) != null) {
078                return graalConstantReflection.readStableFieldValue(field, receiver, true);
079            }
080        }
081        return graalConstantReflection.readConstantFieldValue(field, receiver);
082    }
083
084    private boolean verifyFieldValue(ResolvedJavaField field, JavaConstant constant) {
085        assert field.getAnnotation(Child.class) == null || constant.isNull() ||
086                        metaAccess.lookupJavaType(com.oracle.truffle.api.nodes.Node.class).isAssignableFrom(metaAccess.lookupJavaType(constant)) : "@Child field value must be a Node: " + field +
087                        ", but was: " + constant;
088        assert field.getAnnotation(Children.class) == null || constant.isNull() || metaAccess.lookupJavaType(constant).isArray() : "@Children field value must be an array: " + field + ", but was: " +
089                        constant;
090        return true;
091    }
092
093    public JavaConstant readFieldValue(JavaField field, JavaConstant receiver) {
094        return graalConstantReflection.readFieldValue(field, receiver);
095    }
096
097    public JavaConstant readStableFieldValue(JavaField field, JavaConstant receiver, boolean isDefaultStable) {
098        return graalConstantReflection.readStableFieldValue(field, receiver, isDefaultStable);
099    }
100
101    public JavaConstant boxPrimitive(JavaConstant source) {
102        return graalConstantReflection.boxPrimitive(source);
103    }
104
105    public JavaConstant unboxPrimitive(JavaConstant source) {
106        return graalConstantReflection.unboxPrimitive(source);
107    }
108
109    public JavaConstant forString(String value) {
110        return graalConstantReflection.forString(value);
111    }
112
113    public ResolvedJavaType asJavaType(Constant constant) {
114        return graalConstantReflection.asJavaType(constant);
115    }
116
117    public MethodHandleAccessProvider getMethodHandleAccess() {
118        return graalConstantReflection.getMethodHandleAccess();
119    }
120
121    public MemoryAccessProvider getMemoryAccessProvider() {
122        return graalConstantReflection.getMemoryAccessProvider();
123    }
124}