001/* 002 * Copyright (c) 2012, 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.amd64; 024 025import static com.oracle.graal.hotspot.HotSpotBackend.*; 026import static jdk.internal.jvmci.amd64.AMD64.*; 027import static jdk.internal.jvmci.code.ValueUtil.*; 028 029import com.oracle.graal.compiler.amd64.*; 030import com.oracle.graal.compiler.common.spi.*; 031import com.oracle.graal.compiler.gen.*; 032import com.oracle.graal.hotspot.*; 033import com.oracle.graal.hotspot.nodes.*; 034import com.oracle.graal.lir.*; 035import com.oracle.graal.lir.amd64.AMD64Move.*; 036import com.oracle.graal.lir.gen.*; 037import com.oracle.graal.nodes.*; 038import com.oracle.graal.nodes.CallTargetNode.*; 039import com.oracle.graal.nodes.spi.*; 040 041import jdk.internal.jvmci.amd64.*; 042import jdk.internal.jvmci.code.*; 043 044import com.oracle.graal.debug.*; 045 046import jdk.internal.jvmci.hotspot.*; 047import jdk.internal.jvmci.meta.*; 048 049/** 050 * LIR generator specialized for AMD64 HotSpot. 051 */ 052public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements HotSpotNodeLIRBuilder { 053 054 private final HotSpotGraalRuntimeProvider runtime; 055 056 public AMD64HotSpotNodeLIRBuilder(HotSpotGraalRuntimeProvider runtime, StructuredGraph graph, LIRGeneratorTool gen) { 057 super(graph, gen); 058 this.runtime = runtime; 059 assert gen instanceof AMD64HotSpotLIRGenerator; 060 assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; 061 ((AMD64HotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); 062 } 063 064 private AMD64HotSpotLIRGenerator getGen() { 065 return (AMD64HotSpotLIRGenerator) gen; 066 } 067 068 @Override 069 protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { 070 HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(Kind.Long)); 071 return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack); 072 } 073 074 @Override 075 protected void emitPrologue(StructuredGraph graph) { 076 077 CallingConvention incomingArguments = gen.getCallingConvention(); 078 079 Value[] params = new Value[incomingArguments.getArgumentCount() + 1]; 080 for (int i = 0; i < params.length - 1; i++) { 081 params[i] = LIRGenerator.toStackKind(incomingArguments.getArgument(i)); 082 if (isStackSlot(params[i])) { 083 StackSlot slot = ValueUtil.asStackSlot(params[i]); 084 if (slot.isInCallerFrame() && !gen.getResult().getLIR().hasArgInCallerFrame()) { 085 gen.getResult().getLIR().setHasArgInCallerFrame(); 086 } 087 } 088 } 089 params[params.length - 1] = rbp.asValue(LIRKind.value(Kind.Long)); 090 091 gen.emitIncomingValues(params); 092 093 getGen().emitSaveRbp(); 094 095 getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); 096 097 for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { 098 Value paramValue = params[param.index()]; 099 assert paramValue.getLIRKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp())); 100 setResult(param, gen.emitMove(paramValue)); 101 } 102 } 103 104 @Override 105 public void visitSafepointNode(SafepointNode i) { 106 LIRFrameState info = state(i); 107 append(new AMD64HotSpotSafepointOp(info, getGen().config, this)); 108 } 109 110 @Override 111 protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 112 InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); 113 if (invokeKind.isIndirect()) { 114 append(new AMD64HotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, runtime.getConfig())); 115 } else { 116 assert invokeKind.isDirect(); 117 HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); 118 assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method."; 119 append(new AMD64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, runtime.getConfig())); 120 } 121 } 122 123 @Override 124 protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 125 if (callTarget instanceof HotSpotIndirectCallTargetNode) { 126 Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()); 127 Value targetAddressSrc = operand(callTarget.computedAddress()); 128 AllocatableValue metaspaceMethodDst = AMD64.rbx.asValue(metaspaceMethodSrc.getLIRKind()); 129 AllocatableValue targetAddressDst = AMD64.rax.asValue(targetAddressSrc.getLIRKind()); 130 gen.emitMove(metaspaceMethodDst, metaspaceMethodSrc); 131 gen.emitMove(targetAddressDst, targetAddressSrc); 132 append(new AMD64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethodDst, targetAddressDst, callState, runtime.getConfig())); 133 } else { 134 super.emitIndirectCall(callTarget, result, parameters, temps, callState); 135 } 136 } 137 138 @Override 139 public void emitPatchReturnAddress(ValueNode address) { 140 append(new AMD64HotSpotPatchReturnAddressOp(gen.load(operand(address)))); 141 } 142 143 @Override 144 public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { 145 Variable handler = gen.load(operand(handlerInCallerPc)); 146 ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); 147 CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); 148 assert outgoingCc.getArgumentCount() == 2; 149 RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0); 150 RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1); 151 gen.emitMove(exceptionFixed, operand(exception)); 152 gen.emitMove(exceptionPcFixed, operand(exceptionPc)); 153 Register thread = getGen().getProviders().getRegisters().getThreadRegister(); 154 AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset, 155 thread, getGen().getSaveRbp().getRbpRescueSlot()); 156 append(op); 157 } 158 159 @Override 160 public void visitFullInfopointNode(FullInfopointNode i) { 161 if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { 162 Debug.log("Ignoring InfopointNode for AFTER_BCI"); 163 } else { 164 super.visitFullInfopointNode(i); 165 } 166 } 167 168 @Override 169 public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { 170 Value expected = gen.loadNonConst(operand(x.expectedValue())); 171 Variable newVal = gen.load(operand(x.newValue())); 172 assert expected.getLIRKind().equals(newVal.getLIRKind()); 173 174 RegisterValue raxLocal = AMD64.rax.asValue(expected.getLIRKind()); 175 gen.emitMove(raxLocal, expected); 176 append(new CompareAndSwapOp(expected.getKind(), raxLocal, getGen().asAddressValue(operand(x.getAddress())), raxLocal, newVal)); 177 178 setResult(x, gen.emitMove(raxLocal)); 179 } 180}