001/* 002 * Copyright (c) 2014, 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 */ 023//JaCoCo Exclude 024package com.oracle.graal.hotspot.replacements.arraycopy; 025 026import jdk.internal.jvmci.code.*; 027import jdk.internal.jvmci.hotspot.*; 028import jdk.internal.jvmci.meta.*; 029 030import com.oracle.graal.compiler.common.spi.*; 031import com.oracle.graal.compiler.common.type.*; 032import com.oracle.graal.graph.*; 033import com.oracle.graal.hotspot.*; 034import com.oracle.graal.hotspot.meta.*; 035import com.oracle.graal.hotspot.nodes.*; 036import com.oracle.graal.nodeinfo.*; 037import com.oracle.graal.nodes.*; 038import com.oracle.graal.nodes.calc.*; 039import com.oracle.graal.nodes.extended.*; 040import com.oracle.graal.nodes.memory.*; 041import com.oracle.graal.nodes.memory.address.*; 042import com.oracle.graal.nodes.spi.*; 043import com.oracle.graal.word.*; 044 045@NodeInfo(allowedUsageTypes = {InputType.Memory, InputType.Value}) 046public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { 047 048 public static final NodeClass<CheckcastArrayCopyCallNode> TYPE = NodeClass.create(CheckcastArrayCopyCallNode.class); 049 @Input ValueNode src; 050 @Input ValueNode srcPos; 051 @Input ValueNode dest; 052 @Input ValueNode destPos; 053 @Input ValueNode length; 054 @Input ValueNode destElemKlass; 055 @Input ValueNode superCheckOffset; 056 057 protected final boolean uninit; 058 059 protected final HotSpotGraalRuntimeProvider runtime; 060 061 protected CheckcastArrayCopyCallNode(@InjectedNodeParameter HotSpotGraalRuntimeProvider runtime, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, 062 ValueNode superCheckOffset, ValueNode destElemKlass, boolean uninit) { 063 super(TYPE, StampFactory.forKind(Kind.Int)); 064 this.src = src; 065 this.srcPos = srcPos; 066 this.dest = dest; 067 this.destPos = destPos; 068 this.length = length; 069 this.superCheckOffset = superCheckOffset; 070 this.destElemKlass = destElemKlass; 071 this.uninit = uninit; 072 this.runtime = runtime; 073 } 074 075 public ValueNode getSource() { 076 return src; 077 } 078 079 public ValueNode getSourcePosition() { 080 return srcPos; 081 } 082 083 public ValueNode getDestination() { 084 return dest; 085 } 086 087 public ValueNode getDestinationPosition() { 088 return destPos; 089 } 090 091 public ValueNode getLength() { 092 return length; 093 } 094 095 public boolean isUninit() { 096 return uninit; 097 } 098 099 private ValueNode computeBase(ValueNode base, ValueNode pos) { 100 FixedWithNextNode basePtr = graph().add(new GetObjectAddressNode(base)); 101 graph().addBeforeFixed(this, basePtr); 102 103 HotSpotJVMCIRuntimeProvider jvmciRuntime = runtime.getJVMCIRuntime(); 104 int shift = CodeUtil.log2(jvmciRuntime.getArrayIndexScale(Kind.Object)); 105 ValueNode scaledIndex = graph().unique(new LeftShiftNode(pos, ConstantNode.forInt(shift, graph()))); 106 ValueNode offset = graph().unique(new AddNode(scaledIndex, ConstantNode.forInt(jvmciRuntime.getArrayBaseOffset(Kind.Object), graph()))); 107 return graph().unique(new OffsetAddressNode(basePtr, offset)); 108 } 109 110 @Override 111 public void lower(LoweringTool tool) { 112 if (graph().getGuardsStage().areFrameStatesAtDeopts()) { 113 ForeignCallDescriptor desc = HotSpotHostForeignCallsProvider.lookupCheckcastArraycopyDescriptor(isUninit()); 114 StructuredGraph graph = graph(); 115 ValueNode srcAddr = computeBase(getSource(), getSourcePosition()); 116 ValueNode destAddr = computeBase(getDestination(), getDestinationPosition()); 117 ValueNode len = getLength(); 118 if (len.stamp().getStackKind() != runtime.getTarget().wordKind) { 119 len = IntegerConvertNode.convert(len, StampFactory.forKind(runtime.getTarget().wordKind), graph()); 120 } 121 ForeignCallNode call = graph.add(new ForeignCallNode(runtime.getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len, superCheckOffset, destElemKlass)); 122 call.setStateAfter(stateAfter()); 123 graph.replaceFixedWithFixed(this, call); 124 } 125 } 126 127 @Override 128 public LocationIdentity getLocationIdentity() { 129 /* 130 * Because of restrictions that the memory graph of snippets matches the original node, 131 * pretend that we kill any. 132 */ 133 return LocationIdentity.any(); 134 } 135 136 @NodeIntrinsic 137 public static native int checkcastArraycopy(Object src, int srcPos, Object dest, int destPos, int length, Word superCheckOffset, Object destElemKlass, @ConstantNodeParameter boolean uninit); 138}