001/*
002 * Copyright (c) 2014, 2015, 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.hotspot.replacements;
024
025import jdk.internal.jvmci.hotspot.*;
026import jdk.internal.jvmci.meta.*;
027
028import com.oracle.graal.compiler.common.calc.*;
029import com.oracle.graal.graph.*;
030import com.oracle.graal.graph.spi.*;
031import com.oracle.graal.hotspot.word.*;
032import com.oracle.graal.nodeinfo.*;
033import com.oracle.graal.nodes.*;
034import com.oracle.graal.nodes.calc.*;
035import com.oracle.graal.nodes.extended.*;
036import com.oracle.graal.nodes.memory.*;
037import com.oracle.graal.nodes.memory.address.*;
038import com.oracle.graal.nodes.spi.*;
039
040/**
041 * Read {@code Class::_klass} to get the hub for a {@link java.lang.Class}. This node mostly exists
042 * to replace {@code _klass._java_mirror._klass} with {@code _klass}. The constant folding could be
043 * handled by
044 * {@link ReadNode#canonicalizeRead(ValueNode, AddressNode, LocationIdentity, CanonicalizerTool)}.
045 */
046@NodeInfo
047public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode {
048    public static final NodeClass<ClassGetHubNode> TYPE = NodeClass.create(ClassGetHubNode.class);
049    @Input protected ValueNode clazz;
050    StampProvider stampProvider;
051
052    public ClassGetHubNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode clazz) {
053        this(stampProvider, clazz, null);
054    }
055
056    public ClassGetHubNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode clazz, ValueNode guard) {
057        super(TYPE, stampProvider.createHubStamp(false), (GuardingNode) guard);
058        this.clazz = clazz;
059        this.stampProvider = stampProvider;
060    }
061
062    @Override
063    public Node canonical(CanonicalizerTool tool) {
064        if (tool.allUsagesAvailable() && hasNoUsages()) {
065            return null;
066        } else {
067            if (clazz.isConstant()) {
068                MetaAccessProvider metaAccess = tool.getMetaAccess();
069                if (metaAccess != null) {
070                    ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(clazz.asJavaConstant());
071                    if (exactType instanceof HotSpotResolvedObjectType) {
072                        HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) exactType;
073                        ConstantNode cn = ConstantNode.forConstant(stamp(), objectType.getObjectHub(), metaAccess);
074                        return cn;
075                    } else if (exactType instanceof HotSpotResolvedPrimitiveType) {
076                        return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, metaAccess);
077                    }
078                }
079            }
080            if (clazz instanceof GetClassNode) {
081                GetClassNode getClass = (GetClassNode) clazz;
082                return new LoadHubNode(stampProvider, getClass.getObject(), null);
083            }
084            if (clazz instanceof HubGetClassNode) {
085                // replace _klass._java_mirror._klass -> _klass
086                return ((HubGetClassNode) clazz).getHub();
087            }
088            return this;
089        }
090    }
091
092    @Override
093    public void lower(LoweringTool tool) {
094        tool.getLowerer().lower(this, tool);
095    }
096
097    @NodeIntrinsic
098    public static native KlassPointer readClass(Class<?> clazz);
099
100    @NodeIntrinsic
101    public static native KlassPointer readClass(Class<?> clazz, GuardingNode guard);
102
103    public ValueNode getValue() {
104        return clazz;
105    }
106
107    @Override
108    public Constant convert(Constant c, ConstantReflectionProvider constantReflection) {
109        ResolvedJavaType exactType = constantReflection.asJavaType(c);
110        if (exactType instanceof HotSpotResolvedObjectType) {
111            HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) exactType;
112            return objectType.getObjectHub();
113        } else {
114            assert exactType instanceof HotSpotResolvedPrimitiveType;
115            return JavaConstant.NULL_POINTER;
116        }
117    }
118
119    @Override
120    public Constant reverse(Constant c, ConstantReflectionProvider constantReflection) {
121        assert !c.equals(JavaConstant.NULL_POINTER);
122        ResolvedJavaType objectType = constantReflection.asJavaType(c);
123        return objectType.getJavaClass();
124    }
125
126    public boolean isLossless() {
127        return false;
128    }
129
130    @Override
131    public boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) {
132        assert op == Condition.EQ || op == Condition.NE;
133        ResolvedJavaType exactType = constantReflection.asJavaType(value);
134        return exactType instanceof HotSpotResolvedObjectType;
135    }
136
137}