001/* 002 * Copyright (c) 2013, 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.hotspot.replacements; 024 025import java.lang.reflect.*; 026 027import com.oracle.graal.debug.*; 028import com.oracle.graal.debug.Debug.*; 029import jdk.internal.jvmci.meta.*; 030 031import com.oracle.graal.graph.*; 032import com.oracle.graal.nodeinfo.*; 033import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 034import com.oracle.graal.nodes.*; 035import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; 036import com.oracle.graal.nodes.java.*; 037import com.oracle.graal.nodes.spi.*; 038import com.oracle.graal.nodes.type.*; 039import com.oracle.graal.replacements.nodes.*; 040 041@NodeInfo 042public final class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider { 043 044 public static final NodeClass<ObjectCloneNode> TYPE = NodeClass.create(ObjectCloneNode.class); 045 046 public ObjectCloneNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode receiver) { 047 super(TYPE, invokeKind, targetMethod, bci, returnType, receiver); 048 } 049 050 @Override 051 protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) { 052 ResolvedJavaType type = StampTool.typeOrNull(getObject()); 053 if (type != null) { 054 if (type.isArray()) { 055 Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getKind()); 056 if (method != null) { 057 final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(method); 058 final Replacements replacements = tool.getReplacements(); 059 StructuredGraph snippetGraph = null; 060 try (Scope s = Debug.scope("ArrayCloneSnippet", snippetMethod)) { 061 snippetGraph = replacements.getSnippet(snippetMethod, null); 062 } catch (Throwable e) { 063 throw Debug.handle(e); 064 } 065 066 assert snippetGraph != null : "ObjectCloneSnippets should be installed"; 067 return lowerReplacement((StructuredGraph) snippetGraph.copy(), tool); 068 } 069 assert false : "unhandled array type " + type.getComponentType().getKind(); 070 } else { 071 Assumptions assumptions = graph().getAssumptions(); 072 type = getConcreteType(getObject().stamp(), assumptions, tool.getMetaAccess()); 073 if (type != null) { 074 StructuredGraph newGraph = new StructuredGraph(AllowAssumptions.from(assumptions != null)); 075 ParameterNode param = newGraph.unique(new ParameterNode(0, getObject().stamp())); 076 NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); 077 newGraph.addAfterFixed(newGraph.start(), newInstance); 078 ReturnNode returnNode = newGraph.add(new ReturnNode(newInstance)); 079 newGraph.addAfterFixed(newInstance, returnNode); 080 081 for (ResolvedJavaField field : type.getInstanceFields(true)) { 082 LoadFieldNode load = newGraph.add(new LoadFieldNode(param, field)); 083 newGraph.addBeforeFixed(returnNode, load); 084 newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load))); 085 } 086 return lowerReplacement(newGraph, tool); 087 } 088 } 089 } 090 return null; 091 } 092}