author | dlong |
Thu, 14 Nov 2019 12:21:00 -0800 | |
changeset 59095 | 03fbcd06b4c0 |
parent 54328 | 37648a9c4a6a |
permissions | -rw-r--r-- |
43972 | 1 |
/* |
54328 | 2 |
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. |
43972 | 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 |
*/ |
|
50858 | 23 |
|
24 |
||
43972 | 25 |
package org.graalvm.compiler.hotspot.amd64; |
26 |
||
27 |
import static jdk.vm.ci.amd64.AMD64.rbp; |
|
28 |
import static jdk.vm.ci.code.ValueUtil.isStackSlot; |
|
46640 | 29 |
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; |
43972 | 30 |
|
54328 | 31 |
import org.graalvm.compiler.api.replacements.Snippet; |
43972 | 32 |
import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder; |
33 |
import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; |
|
34 |
import org.graalvm.compiler.core.common.LIRKind; |
|
54328 | 35 |
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; |
43972 | 36 |
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; |
37 |
import org.graalvm.compiler.core.gen.DebugInfoBuilder; |
|
38 |
import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; |
|
39 |
import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; |
|
40 |
import org.graalvm.compiler.hotspot.HotSpotLockStack; |
|
41 |
import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; |
|
42 |
import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; |
|
43 |
import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; |
|
44 |
import org.graalvm.compiler.lir.LIRFrameState; |
|
45 |
import org.graalvm.compiler.lir.Variable; |
|
46 |
import org.graalvm.compiler.lir.amd64.AMD64BreakpointOp; |
|
47 |
import org.graalvm.compiler.lir.gen.LIRGeneratorTool; |
|
48 |
import org.graalvm.compiler.nodes.BreakpointNode; |
|
49 |
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; |
|
50 |
import org.graalvm.compiler.nodes.DirectCallTargetNode; |
|
51 |
import org.graalvm.compiler.nodes.FullInfopointNode; |
|
52 |
import org.graalvm.compiler.nodes.IndirectCallTargetNode; |
|
48190 | 53 |
import org.graalvm.compiler.nodes.NodeView; |
43972 | 54 |
import org.graalvm.compiler.nodes.ParameterNode; |
55 |
import org.graalvm.compiler.nodes.SafepointNode; |
|
56 |
import org.graalvm.compiler.nodes.StructuredGraph; |
|
57 |
import org.graalvm.compiler.nodes.ValueNode; |
|
58 |
import org.graalvm.compiler.nodes.spi.NodeValueMap; |
|
54328 | 59 |
import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; |
60 |
import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; |
|
43972 | 61 |
|
62 |
import jdk.vm.ci.amd64.AMD64; |
|
63 |
import jdk.vm.ci.amd64.AMD64Kind; |
|
64 |
import jdk.vm.ci.code.BytecodeFrame; |
|
65 |
import jdk.vm.ci.code.CallingConvention; |
|
66 |
import jdk.vm.ci.code.Register; |
|
67 |
import jdk.vm.ci.code.RegisterValue; |
|
68 |
import jdk.vm.ci.code.StackSlot; |
|
69 |
import jdk.vm.ci.code.ValueUtil; |
|
70 |
import jdk.vm.ci.hotspot.HotSpotCallingConventionType; |
|
71 |
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; |
|
72 |
import jdk.vm.ci.meta.AllocatableValue; |
|
54328 | 73 |
import jdk.vm.ci.meta.JavaKind; |
43972 | 74 |
import jdk.vm.ci.meta.JavaType; |
54328 | 75 |
import jdk.vm.ci.meta.ResolvedJavaMethod; |
43972 | 76 |
import jdk.vm.ci.meta.Value; |
54328 | 77 |
import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; |
43972 | 78 |
|
79 |
/** |
|
80 |
* LIR generator specialized for AMD64 HotSpot. |
|
81 |
*/ |
|
82 |
public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements HotSpotNodeLIRBuilder { |
|
83 |
||
84 |
public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, AMD64NodeMatchRules nodeMatchRules) { |
|
85 |
super(graph, gen, nodeMatchRules); |
|
86 |
assert gen instanceof AMD64HotSpotLIRGenerator; |
|
87 |
assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; |
|
88 |
((AMD64HotSpotLIRGenerator) gen).setDebugInfoBuilder(((HotSpotDebugInfoBuilder) getDebugInfoBuilder())); |
|
89 |
} |
|
90 |
||
91 |
private AMD64HotSpotLIRGenerator getGen() { |
|
92 |
return (AMD64HotSpotLIRGenerator) gen; |
|
93 |
} |
|
94 |
||
95 |
@Override |
|
96 |
protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { |
|
97 |
HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(AMD64Kind.QWORD)); |
|
98 |
return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack, (HotSpotLIRGenerator) gen); |
|
99 |
} |
|
100 |
||
101 |
@Override |
|
102 |
protected void emitPrologue(StructuredGraph graph) { |
|
103 |
||
104 |
CallingConvention incomingArguments = gen.getResult().getCallingConvention(); |
|
105 |
||
106 |
Value[] params = new Value[incomingArguments.getArgumentCount() + 1]; |
|
107 |
for (int i = 0; i < params.length - 1; i++) { |
|
108 |
params[i] = incomingArguments.getArgument(i); |
|
109 |
if (isStackSlot(params[i])) { |
|
110 |
StackSlot slot = ValueUtil.asStackSlot(params[i]); |
|
111 |
if (slot.isInCallerFrame() && !gen.getResult().getLIR().hasArgInCallerFrame()) { |
|
112 |
gen.getResult().getLIR().setHasArgInCallerFrame(); |
|
113 |
} |
|
114 |
} |
|
115 |
} |
|
116 |
params[params.length - 1] = rbp.asValue(LIRKind.value(AMD64Kind.QWORD)); |
|
117 |
||
118 |
gen.emitIncomingValues(params); |
|
119 |
||
120 |
getGen().emitSaveRbp(); |
|
121 |
||
122 |
getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); |
|
123 |
||
124 |
for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { |
|
125 |
Value paramValue = params[param.index()]; |
|
48190 | 126 |
assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp(NodeView.DEFAULT))) : paramValue.getValueKind() + " != " + param.stamp(NodeView.DEFAULT); |
43972 | 127 |
setResult(param, gen.emitMove(paramValue)); |
128 |
} |
|
129 |
} |
|
130 |
||
131 |
@Override |
|
132 |
public void visitSafepointNode(SafepointNode i) { |
|
133 |
LIRFrameState info = state(i); |
|
48172
e26fc5201707
8191437: AOT doesn't work easily after thread local handshakes
dlong
parents:
47798
diff
changeset
|
134 |
Register thread = getGen().getProviders().getRegisters().getThreadRegister(); |
e26fc5201707
8191437: AOT doesn't work easily after thread local handshakes
dlong
parents:
47798
diff
changeset
|
135 |
append(new AMD64HotSpotSafepointOp(info, getGen().config, this, thread)); |
43972 | 136 |
} |
137 |
||
138 |
@Override |
|
139 |
protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { |
|
140 |
InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); |
|
141 |
if (invokeKind.isIndirect()) { |
|
142 |
append(new AMD64HotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); |
|
143 |
} else { |
|
144 |
assert invokeKind.isDirect(); |
|
145 |
HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); |
|
146 |
assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method."; |
|
147 |
append(new AMD64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); |
|
148 |
} |
|
149 |
} |
|
150 |
||
151 |
@Override |
|
152 |
protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { |
|
153 |
if (callTarget instanceof HotSpotIndirectCallTargetNode) { |
|
154 |
Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()); |
|
155 |
Value targetAddressSrc = operand(callTarget.computedAddress()); |
|
156 |
AllocatableValue metaspaceMethodDst = AMD64.rbx.asValue(metaspaceMethodSrc.getValueKind()); |
|
157 |
AllocatableValue targetAddressDst = AMD64.rax.asValue(targetAddressSrc.getValueKind()); |
|
158 |
gen.emitMove(metaspaceMethodDst, metaspaceMethodSrc); |
|
159 |
gen.emitMove(targetAddressDst, targetAddressSrc); |
|
160 |
append(new AMD64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethodDst, targetAddressDst, callState, getGen().config)); |
|
161 |
} else { |
|
162 |
super.emitIndirectCall(callTarget, result, parameters, temps, callState); |
|
163 |
} |
|
164 |
} |
|
165 |
||
166 |
@Override |
|
167 |
public void emitPatchReturnAddress(ValueNode address) { |
|
168 |
append(new AMD64HotSpotPatchReturnAddressOp(gen.load(operand(address)))); |
|
169 |
} |
|
170 |
||
171 |
@Override |
|
172 |
public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { |
|
173 |
Variable handler = gen.load(operand(handlerInCallerPc)); |
|
174 |
ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); |
|
175 |
CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); |
|
176 |
assert outgoingCc.getArgumentCount() == 2; |
|
177 |
RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0); |
|
178 |
RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1); |
|
179 |
gen.emitMove(exceptionFixed, operand(exception)); |
|
180 |
gen.emitMove(exceptionPcFixed, operand(exceptionPc)); |
|
181 |
Register thread = getGen().getProviders().getRegisters().getThreadRegister(); |
|
182 |
AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset, |
|
183 |
thread); |
|
184 |
append(op); |
|
185 |
} |
|
186 |
||
187 |
@Override |
|
188 |
public void visitFullInfopointNode(FullInfopointNode i) { |
|
189 |
if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { |
|
46640 | 190 |
i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); |
43972 | 191 |
} else { |
192 |
super.visitFullInfopointNode(i); |
|
193 |
} |
|
194 |
} |
|
195 |
||
196 |
@Override |
|
197 |
public void visitBreakpointNode(BreakpointNode node) { |
|
198 |
JavaType[] sig = new JavaType[node.arguments().size()]; |
|
199 |
for (int i = 0; i < sig.length; i++) { |
|
48190 | 200 |
sig[i] = node.arguments().get(i).stamp(NodeView.DEFAULT).javaType(gen.getMetaAccess()); |
43972 | 201 |
} |
202 |
||
47798 | 203 |
Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments()); |
43972 | 204 |
append(new AMD64BreakpointOp(parameters)); |
205 |
} |
|
54328 | 206 |
|
207 |
private ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { |
|
208 |
return getGen().getForeignCalls().lookupForeignCall(descriptor); |
|
209 |
} |
|
210 |
||
211 |
@Override |
|
212 |
public ForeignCallLinkage lookupGraalStub(ValueNode valueNode) { |
|
213 |
ResolvedJavaMethod method = valueNode.graph().method(); |
|
214 |
if (method == null || method.getAnnotation(Snippet.class) != null) { |
|
215 |
// Emit assembly for snippet stubs |
|
216 |
return null; |
|
217 |
} |
|
218 |
||
219 |
if (valueNode instanceof ArrayEqualsNode) { |
|
220 |
ArrayEqualsNode arrayEqualsNode = (ArrayEqualsNode) valueNode; |
|
221 |
JavaKind kind = arrayEqualsNode.getKind(); |
|
222 |
ValueNode length = arrayEqualsNode.getLength(); |
|
223 |
||
224 |
if (length.isConstant()) { |
|
225 |
int constantLength = length.asJavaConstant().asInt(); |
|
226 |
if (constantLength >= 0 && constantLength * kind.getByteCount() < 2 * getGen().getMaxVectorSize()) { |
|
227 |
// Yield constant-length arrays comparison assembly |
|
228 |
return null; |
|
229 |
} |
|
230 |
} |
|
231 |
||
232 |
switch (kind) { |
|
233 |
case Boolean: |
|
234 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS); |
|
235 |
case Byte: |
|
236 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS); |
|
237 |
case Char: |
|
238 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS); |
|
239 |
case Short: |
|
240 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS); |
|
241 |
case Int: |
|
242 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS); |
|
243 |
case Long: |
|
244 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS); |
|
245 |
case Float: |
|
246 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS); |
|
247 |
case Double: |
|
248 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS); |
|
249 |
default: |
|
250 |
return null; |
|
251 |
} |
|
252 |
} else if (valueNode instanceof ArrayCompareToNode) { |
|
253 |
ArrayCompareToNode arrayCompareToNode = (ArrayCompareToNode) valueNode; |
|
254 |
JavaKind kind1 = arrayCompareToNode.getKind1(); |
|
255 |
JavaKind kind2 = arrayCompareToNode.getKind2(); |
|
256 |
||
257 |
if (kind1 == JavaKind.Byte) { |
|
258 |
if (kind2 == JavaKind.Byte) { |
|
259 |
return lookupForeignCall(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_BYTE_ARRAY); |
|
260 |
} else if (kind2 == JavaKind.Char) { |
|
261 |
return lookupForeignCall(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_CHAR_ARRAY); |
|
262 |
} |
|
263 |
} else if (kind1 == JavaKind.Char) { |
|
264 |
if (kind2 == JavaKind.Byte) { |
|
265 |
return lookupForeignCall(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_BYTE_ARRAY); |
|
266 |
} else if (kind2 == JavaKind.Char) { |
|
267 |
return lookupForeignCall(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_CHAR_ARRAY); |
|
268 |
} |
|
269 |
} |
|
270 |
} else if (valueNode instanceof ArrayRegionEqualsNode) { |
|
271 |
ArrayRegionEqualsNode arrayRegionEqualsNode = (ArrayRegionEqualsNode) valueNode; |
|
272 |
JavaKind kind1 = arrayRegionEqualsNode.getKind1(); |
|
273 |
JavaKind kind2 = arrayRegionEqualsNode.getKind2(); |
|
274 |
ValueNode length = arrayRegionEqualsNode.getLength(); |
|
275 |
||
276 |
if (length.isConstant()) { |
|
277 |
int constantLength = length.asJavaConstant().asInt(); |
|
278 |
if (constantLength >= 0 && constantLength * (Math.max(kind1.getByteCount(), kind2.getByteCount())) < 2 * getGen().getMaxVectorSize()) { |
|
279 |
// Yield constant-length arrays comparison assembly |
|
280 |
return null; |
|
281 |
} |
|
282 |
} |
|
283 |
||
284 |
if (kind1 == kind2) { |
|
285 |
switch (kind1) { |
|
286 |
case Byte: |
|
287 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS_DIRECT); |
|
288 |
case Char: |
|
289 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_DIRECT); |
|
290 |
default: |
|
291 |
return null; |
|
292 |
} |
|
293 |
} else if (kind1 == JavaKind.Char && kind2 == JavaKind.Byte) { |
|
294 |
return lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_BYTE_ARRAY); |
|
295 |
} |
|
296 |
} |
|
297 |
||
298 |
return null; |
|
299 |
} |
|
43972 | 300 |
} |