--- /dev/null 2017-01-22 10:16:57.869617664 -0800 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java 2017-02-15 16:58:51.866289877 -0800 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static jdk.vm.ci.aarch64.AArch64.lr; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; +import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.inlineCacheRegister; +import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.metaspaceMethodRegister; + +import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder; +import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.core.gen.DebugInfoBuilder; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; +import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; +import org.graalvm.compiler.hotspot.HotSpotLockStack; +import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; +import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; +import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; +import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.aarch64.AArch64BreakpointOp; +import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.nodes.BreakpointNode; +import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; +import org.graalvm.compiler.nodes.DirectCallTargetNode; +import org.graalvm.compiler.nodes.FullInfopointNode; +import org.graalvm.compiler.nodes.IndirectCallTargetNode; +import org.graalvm.compiler.nodes.ParameterNode; +import org.graalvm.compiler.nodes.SafepointNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.NodeValueMap; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.hotspot.HotSpotCallingConventionType; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.Value; +import jdk.vm.ci.meta.ValueKind; + +/** + * LIR generator specialized for AArch64 HotSpot. + */ +public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implements HotSpotNodeLIRBuilder { + + public AArch64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, AArch64NodeMatchRules nodeMatchRules) { + super(graph, gen, nodeMatchRules); + assert gen instanceof AArch64HotSpotLIRGenerator; + assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; + ((AArch64HotSpotLIRGenerator) gen).setDebugInfoBuilder(((HotSpotDebugInfoBuilder) getDebugInfoBuilder())); + } + + @Override + protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { + HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(AArch64Kind.QWORD)); + return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack, (HotSpotLIRGenerator) gen); + } + + private AArch64HotSpotLIRGenerator getGen() { + return (AArch64HotSpotLIRGenerator) gen; + } + + @Override + protected void emitPrologue(StructuredGraph graph) { + CallingConvention incomingArguments = gen.getResult().getCallingConvention(); + Value[] params = new Value[incomingArguments.getArgumentCount() + 2]; + for (int i = 0; i < incomingArguments.getArgumentCount(); i++) { + params[i] = incomingArguments.getArgument(i); + if (isStackSlot(params[i])) { + StackSlot slot = ValueUtil.asStackSlot(params[i]); + if (slot.isInCallerFrame() && !gen.getResult().getLIR().hasArgInCallerFrame()) { + gen.getResult().getLIR().setHasArgInCallerFrame(); + } + } + } + params[params.length - 2] = fp.asValue(LIRKind.value(AArch64Kind.QWORD)); + params[params.length - 1] = lr.asValue(LIRKind.value(AArch64Kind.QWORD)); + + gen.emitIncomingValues(params); + + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { + Value paramValue = params[param.index()]; + assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp())) : paramValue.getValueKind() + " != " + param.stamp(); + setResult(param, gen.emitMove(paramValue)); + } + } + + @Override + public void visitSafepointNode(SafepointNode i) { + LIRFrameState info = state(i); + Variable scratch = gen.newVariable(LIRKind.value(getGen().target().arch.getWordKind())); + append(new AArch64HotSpotSafepointOp(info, getGen().config, scratch)); + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); + if (invokeKind.isIndirect()) { + append(new AArch64HotSpotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); + } else { + assert invokeKind.isDirect(); + HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); + assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method."; + append(new AArch64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); + } + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()); + Value targetAddressSrc = operand(callTarget.computedAddress()); + AllocatableValue metaspaceMethodDst = metaspaceMethodRegister.asValue(metaspaceMethodSrc.getValueKind()); + AllocatableValue targetAddressDst = inlineCacheRegister.asValue(targetAddressSrc.getValueKind()); + gen.emitMove(metaspaceMethodDst, metaspaceMethodSrc); + gen.emitMove(targetAddressDst, targetAddressSrc); + append(new AArch64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethodDst, targetAddressDst, callState, getGen().config)); + } + + @Override + public void emitPatchReturnAddress(ValueNode address) { + append(new AArch64HotSpotPatchReturnAddressOp(gen.load(operand(address)))); + } + + @Override + public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { + Variable handler = gen.load(operand(handlerInCallerPc)); + ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); + CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); + assert outgoingCc.getArgumentCount() == 2; + RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0); + RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1); + gen.emitMove(exceptionFixed, operand(exception)); + gen.emitMove(exceptionPcFixed, operand(exceptionPc)); + Register thread = getGen().getProviders().getRegisters().getThreadRegister(); + AArch64HotSpotJumpToExceptionHandlerInCallerOp op = new AArch64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, + getGen().config.threadIsMethodHandleReturnOffset, thread, getGen().config); + append(op); + } + + @Override + public void visitFullInfopointNode(FullInfopointNode i) { + if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { + Debug.log("Ignoring InfopointNode for AFTER_BCI"); + } else { + super.visitFullInfopointNode(i); + } + } + + @Override + public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { + AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); + AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); + AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); + ValueKind kind = cmpValue.getValueKind(); + assert kind.equals(newValue.getValueKind()); + + Variable result = gen.newVariable(newValue.getValueKind()); + Variable scratch = gen.newVariable(LIRKind.value(AArch64Kind.DWORD)); + append(new CompareAndSwapOp(result, cmpValue, newValue, address, scratch)); + setResult(x, result); + } + + @Override + public void visitBreakpointNode(BreakpointNode node) { + JavaType[] sig = new JavaType[node.arguments().size()]; + for (int i = 0; i < sig.length; i++) { + sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); + } + + Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), + node.arguments()); + append(new AArch64BreakpointOp(parameters)); + } +}