001/*
002 * Copyright (c) 2009, 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.nodes.java;
024
025import jdk.internal.jvmci.meta.*;
026
027import com.oracle.graal.graph.*;
028import com.oracle.graal.graph.spi.*;
029import com.oracle.graal.nodeinfo.*;
030import com.oracle.graal.nodes.*;
031import com.oracle.graal.nodes.spi.*;
032import com.oracle.graal.nodes.type.*;
033
034/**
035 * Implements a type check where the type being checked is loaded at runtime. This is used, for
036 * instance, to implement an object array store check.
037 */
038@NodeInfo
039public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
040
041    public static final NodeClass<CheckCastDynamicNode> TYPE = NodeClass.create(CheckCastDynamicNode.class);
042    @Input ValueNode object;
043    @Input ValueNode hub;
044
045    /**
046     * Determines the exception thrown by this node if the check fails: {@link ClassCastException}
047     * if false; {@link ArrayStoreException} if true.
048     */
049    protected final boolean forStoreCheck;
050
051    public CheckCastDynamicNode(ValueNode hub, ValueNode object, boolean forStoreCheck) {
052        super(TYPE, object.stamp());
053        this.hub = hub;
054        this.object = object;
055        this.forStoreCheck = forStoreCheck;
056    }
057
058    public ValueNode object() {
059        return object;
060    }
061
062    /**
063     * Gets the runtime-loaded type being cast to.
064     */
065    public ValueNode hub() {
066        return hub;
067    }
068
069    public ValueNode getX() {
070        return object;
071    }
072
073    public ValueNode getY() {
074        return hub;
075    }
076
077    public boolean isForStoreCheck() {
078        return forStoreCheck;
079    }
080
081    @Override
082    public void lower(LoweringTool tool) {
083        tool.getLowerer().lower(this, tool);
084    }
085
086    @Override
087    public boolean inferStamp() {
088        return updateStamp(object().stamp());
089    }
090
091    @Override
092    public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forHub) {
093        if (StampTool.isPointerAlwaysNull(forObject)) {
094            return forObject;
095        }
096        if (forHub.isConstant()) {
097            ResolvedJavaType t = tool.getConstantReflection().asJavaType(forHub.asConstant());
098            if (t != null) {
099                return new CheckCastNode(t, forObject, null, forStoreCheck);
100            }
101        }
102        return this;
103    }
104}