ObjectCloneNode.java revision 12651:6ef01bd40ce2
1/*
2 * Copyright (c) 2013, 2015, 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 */
23package org.graalvm.compiler.hotspot.replacements;
24
25import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID;
26
27import java.lang.reflect.Method;
28
29import org.graalvm.compiler.core.common.type.StampPair;
30import org.graalvm.compiler.debug.Debug;
31import org.graalvm.compiler.debug.Debug.Scope;
32import org.graalvm.compiler.graph.NodeClass;
33import org.graalvm.compiler.nodeinfo.NodeInfo;
34import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
35import org.graalvm.compiler.nodes.ParameterNode;
36import org.graalvm.compiler.nodes.ReturnNode;
37import org.graalvm.compiler.nodes.StructuredGraph;
38import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
39import org.graalvm.compiler.nodes.ValueNode;
40import org.graalvm.compiler.nodes.java.LoadFieldNode;
41import org.graalvm.compiler.nodes.java.NewInstanceNode;
42import org.graalvm.compiler.nodes.java.StoreFieldNode;
43import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
44import org.graalvm.compiler.nodes.spi.LoweringTool;
45import org.graalvm.compiler.nodes.spi.Replacements;
46import org.graalvm.compiler.nodes.spi.VirtualizableAllocation;
47import org.graalvm.compiler.nodes.type.StampTool;
48import org.graalvm.compiler.replacements.nodes.BasicObjectCloneNode;
49
50import jdk.vm.ci.meta.Assumptions;
51import jdk.vm.ci.meta.ResolvedJavaField;
52import jdk.vm.ci.meta.ResolvedJavaMethod;
53import jdk.vm.ci.meta.ResolvedJavaType;
54
55@NodeInfo
56public final class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider {
57
58    public static final NodeClass<ObjectCloneNode> TYPE = NodeClass.create(ObjectCloneNode.class);
59
60    public ObjectCloneNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, StampPair returnStamp, ValueNode receiver) {
61        super(TYPE, invokeKind, targetMethod, bci, returnStamp, receiver);
62    }
63
64    @Override
65    @SuppressWarnings("try")
66    protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
67        ResolvedJavaType type = StampTool.typeOrNull(getObject());
68        if (type != null) {
69            if (type.isArray()) {
70                Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getJavaKind());
71                if (method != null) {
72                    final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(method);
73                    final Replacements replacements = tool.getReplacements();
74                    StructuredGraph snippetGraph = null;
75                    try (Scope s = Debug.scope("ArrayCloneSnippet", snippetMethod)) {
76                        snippetGraph = replacements.getSnippet(snippetMethod, null);
77                    } catch (Throwable e) {
78                        throw Debug.handle(e);
79                    }
80
81                    assert snippetGraph != null : "ObjectCloneSnippets should be installed";
82                    return lowerReplacement((StructuredGraph) snippetGraph.copy(), tool);
83                }
84                assert false : "unhandled array type " + type.getComponentType().getJavaKind();
85            } else {
86                Assumptions assumptions = graph().getAssumptions();
87                type = getConcreteType(getObject().stamp());
88                if (type != null) {
89                    StructuredGraph newGraph = new StructuredGraph(AllowAssumptions.from(assumptions != null), INVALID_COMPILATION_ID);
90                    ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp())));
91                    NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true));
92                    newGraph.addAfterFixed(newGraph.start(), newInstance);
93                    ReturnNode returnNode = newGraph.add(new ReturnNode(newInstance));
94                    newGraph.addAfterFixed(newInstance, returnNode);
95
96                    for (ResolvedJavaField field : type.getInstanceFields(true)) {
97                        LoadFieldNode load = newGraph.add(LoadFieldNode.create(newGraph.getAssumptions(), param, field));
98                        newGraph.addBeforeFixed(returnNode, load);
99                        newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load)));
100                    }
101                    return lowerReplacement(newGraph, tool);
102                }
103            }
104        }
105        return null;
106    }
107}
108