001/* 002 * Copyright (c) 2015, 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.memory.address; 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.calc.*; 033import com.oracle.graal.nodes.spi.*; 034import com.oracle.graal.nodes.type.*; 035 036/** 037 * Represents an address that is composed of a base and an offset. The base can be either a 038 * {@link Kind#Object}, a word-sized integer or another pointer. The offset must be a word-sized 039 * integer. 040 */ 041@NodeInfo(allowedUsageTypes = InputType.Association) 042public class OffsetAddressNode extends AddressNode implements Canonicalizable, PiPushable { 043 public static final NodeClass<OffsetAddressNode> TYPE = NodeClass.create(OffsetAddressNode.class); 044 045 @Input ValueNode base; 046 @Input ValueNode offset; 047 048 public OffsetAddressNode(ValueNode base, ValueNode offset) { 049 super(TYPE); 050 this.base = base; 051 this.offset = offset; 052 } 053 054 public ValueNode getBase() { 055 return base; 056 } 057 058 public void setBase(ValueNode base) { 059 updateUsages(this.base, base); 060 this.base = base; 061 } 062 063 public ValueNode getOffset() { 064 return offset; 065 } 066 067 public void setOffset(ValueNode offset) { 068 updateUsages(this.offset, offset); 069 this.offset = offset; 070 } 071 072 public Node canonical(CanonicalizerTool tool) { 073 if (base instanceof RawAddressNode) { 074 // The RawAddressNode is redundant, just directly use its input as base. 075 return new OffsetAddressNode(((RawAddressNode) base).getAddress(), offset); 076 } else if (base instanceof OffsetAddressNode) { 077 // Rewrite (&base[offset1])[offset2] to base[offset1 + offset2]. 078 OffsetAddressNode b = (OffsetAddressNode) base; 079 return new OffsetAddressNode(b.getBase(), BinaryArithmeticNode.add(b.getOffset(), this.getOffset())); 080 } else { 081 return this; 082 } 083 } 084 085 @Override 086 public boolean push(PiNode parent) { 087 if (!(offset.isConstant() && parent.stamp() instanceof ObjectStamp && parent.object().stamp() instanceof ObjectStamp)) { 088 return false; 089 } 090 091 ObjectStamp piStamp = (ObjectStamp) parent.stamp(); 092 ResolvedJavaType receiverType = piStamp.type(); 093 if (receiverType == null) { 094 return false; 095 } 096 ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(offset.asJavaConstant().asLong(), Kind.Void); 097 if (field == null) { 098 // field was not declared by receiverType 099 return false; 100 } 101 102 ObjectStamp valueStamp = (ObjectStamp) parent.object().stamp(); 103 ResolvedJavaType valueType = StampTool.typeOrNull(valueStamp); 104 if (valueType != null && field.getDeclaringClass().isAssignableFrom(valueType)) { 105 if (piStamp.nonNull() == valueStamp.nonNull() && piStamp.alwaysNull() == valueStamp.alwaysNull()) { 106 replaceFirstInput(parent, parent.object()); 107 return true; 108 } 109 } 110 111 return false; 112 } 113 114 @NodeIntrinsic 115 public static native Address address(Object base, long offset); 116}