1 /*
2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 
25 package org.graalvm.compiler.nodes;
26 
27 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
28 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
29 
30 import jdk.vm.ci.meta.ConstantReflectionProvider;
31 import org.graalvm.compiler.core.common.type.Stamp;
32 import org.graalvm.compiler.graph.Node;
33 import org.graalvm.compiler.graph.NodeClass;
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
35 import org.graalvm.compiler.nodeinfo.NodeInfo;
36 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
37 import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
38 import org.graalvm.compiler.nodes.util.GraphUtil;
39 
40 /**
41  * A {@link PiNode} that also provides an array length in addition to a more refined stamp. A usage
42  * that reads the array length, such as an {@link ArrayLengthNode}, can be canonicalized based on
43  * this information.
44  */
45 @NodeInfo
46 public final class PiArrayNode extends PiNode implements ArrayLengthProvider {
47 
48     public static final NodeClass<PiArrayNode> TYPE = NodeClass.create(PiArrayNode.class);
49     @Input ValueNode length;
50 
51     @Override
findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection)52     public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
53         return length;
54     }
55 
PiArrayNode(ValueNode object, ValueNode length, Stamp stamp)56     public PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) {
57         super(TYPE, object, stamp, null);
58         this.length = length;
59     }
60 
61     @Override
canonical(CanonicalizerTool tool)62     public Node canonical(CanonicalizerTool tool) {
63         if (GraphUtil.arrayLength(object(), ArrayLengthProvider.FindLengthMode.SEARCH_ONLY, tool.getConstantReflection()) != length) {
64             return this;
65         }
66         return super.canonical(tool);
67     }
68 
69     /**
70      * Changes the stamp of an object inside a snippet to be the stamp of the node replaced by the
71      * snippet.
72      */
73     @NodeIntrinsic(Placeholder.class)
piArrayCastToSnippetReplaceeStamp(Object object, int length)74     public static native Object piArrayCastToSnippetReplaceeStamp(Object object, int length);
75 
76     /**
77      * A placeholder node in a snippet that will be replaced with a {@link PiArrayNode} when the
78      * snippet is instantiated.
79      */
80     @NodeInfo(cycles = CYCLES_0, size = SIZE_0)
81     public static class Placeholder extends PiNode.Placeholder {
82 
83         public static final NodeClass<Placeholder> TYPE = NodeClass.create(Placeholder.class);
84         @Input ValueNode length;
85 
Placeholder(ValueNode object, ValueNode length)86         protected Placeholder(ValueNode object, ValueNode length) {
87             super(TYPE, object);
88             this.length = length;
89         }
90 
91         @Override
makeReplacement(Stamp snippetReplaceeStamp)92         public void makeReplacement(Stamp snippetReplaceeStamp) {
93             PiArrayNode piArray = graph().addOrUnique(new PiArrayNode(object(), length, snippetReplaceeStamp));
94             replaceAndDelete(piArray);
95         }
96     }
97 }
98