001/* 002 * Copyright (c) 2009, 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.nodes.extended; 024 025import jdk.internal.jvmci.meta.*; 026 027import com.oracle.graal.compiler.common.type.*; 028import com.oracle.graal.graph.*; 029import com.oracle.graal.graph.spi.*; 030import com.oracle.graal.nodeinfo.*; 031import com.oracle.graal.nodes.*; 032import com.oracle.graal.nodes.spi.*; 033import com.oracle.graal.nodes.type.*; 034import com.oracle.graal.nodes.virtual.*; 035 036/** 037 * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. It 038 * allows unsafe casts "sideways" in the type hierarchy. It does not allow to "drop" type 039 * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type 040 * than the type this nodes casts to. 041 */ 042@NodeInfo 043public final class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { 044 045 public static final NodeClass<UnsafeCastNode> TYPE = NodeClass.create(UnsafeCastNode.class); 046 @Input ValueNode object; 047 048 public UnsafeCastNode(ValueNode object, Stamp stamp) { 049 super(TYPE, stamp); 050 this.object = object; 051 } 052 053 public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) { 054 super(TYPE, stamp, (GuardingNode) anchor); 055 this.object = object; 056 } 057 058 public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { 059 this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || StampTool.isPointerNonNull(object.stamp()), true) : StampFactory.forKind(toType.getKind())); 060 } 061 062 @Override 063 public ValueNode getOriginalNode() { 064 return object; 065 } 066 067 @Override 068 public Node canonical(CanonicalizerTool tool) { 069 assert getKind() == Kind.Object && object.getKind() == Kind.Object; 070 071 ObjectStamp my = (ObjectStamp) stamp(); 072 ObjectStamp other = (ObjectStamp) object.stamp(); 073 074 if (my.type() == null || other.type() == null) { 075 return this; 076 } 077 if (my.isExactType() && !other.isExactType()) { 078 return this; 079 } 080 if (my.nonNull() && !other.nonNull()) { 081 return this; 082 } 083 if (!my.type().isAssignableFrom(other.type())) { 084 return this; 085 } 086 /* 087 * The unsafe cast does not add any new type information, so it can be removed. Note that 088 * this means that the unsafe cast cannot be used to "drop" type information (in which case 089 * it must not be canonicalized in any case). 090 */ 091 return object; 092 } 093 094 @Override 095 public void virtualize(VirtualizerTool tool) { 096 ValueNode alias = tool.getAlias(object); 097 if (alias instanceof VirtualObjectNode) { 098 VirtualObjectNode virtual = (VirtualObjectNode) alias; 099 if (StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(virtual.type())) { 100 tool.replaceWithVirtual(virtual); 101 } 102 } 103 } 104 105 @Override 106 public void generate(NodeLIRBuilderTool generator) { 107 assert getKind() == Kind.Object && object.getKind() == Kind.Object; 108 /* 109 * The LIR only cares about the kind of an operand, not the actual type of an object. So we 110 * do not have to introduce a new operand. 111 */ 112 generator.setResult(this, generator.operand(object)); 113 } 114}