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 */ 23 24 25 package org.graalvm.compiler.hotspot.aarch64; 26 27 import static java.lang.reflect.Modifier.isStatic; 28 import static jdk.vm.ci.aarch64.AArch64.lr; 29 import static jdk.vm.ci.aarch64.AArch64.r10; 30 import static jdk.vm.ci.aarch64.AArch64.sp; 31 import static jdk.vm.ci.aarch64.AArch64.zr; 32 import static jdk.vm.ci.code.ValueUtil.asRegister; 33 import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; 34 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 35 import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; 36 37 import jdk.internal.vm.compiler.collections.EconomicSet; 38 import org.graalvm.compiler.asm.Assembler; 39 import org.graalvm.compiler.asm.Label; 40 import org.graalvm.compiler.asm.aarch64.AArch64Address; 41 import org.graalvm.compiler.asm.aarch64.AArch64Assembler; 42 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; 43 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; 44 import org.graalvm.compiler.code.CompilationResult; 45 import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; 46 import org.graalvm.compiler.core.common.CompilationIdentifier; 47 import org.graalvm.compiler.core.common.LIRKind; 48 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; 49 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 50 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 51 import org.graalvm.compiler.hotspot.HotSpotDataBuilder; 52 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 53 import org.graalvm.compiler.hotspot.HotSpotHostBackend; 54 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; 55 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; 56 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; 57 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 58 import org.graalvm.compiler.hotspot.stubs.Stub; 59 import org.graalvm.compiler.lir.LIR; 60 import org.graalvm.compiler.lir.aarch64.AArch64Call; 61 import org.graalvm.compiler.lir.aarch64.AArch64FrameMap; 62 import org.graalvm.compiler.lir.aarch64.AArch64FrameMapBuilder; 63 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 64 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; 65 import org.graalvm.compiler.lir.asm.DataBuilder; 66 import org.graalvm.compiler.lir.asm.FrameContext; 67 import org.graalvm.compiler.lir.framemap.FrameMap; 68 import org.graalvm.compiler.lir.framemap.FrameMapBuilder; 69 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 70 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 71 import org.graalvm.compiler.nodes.StructuredGraph; 72 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 73 74 import jdk.vm.ci.aarch64.AArch64Kind; 75 import jdk.vm.ci.code.CallingConvention; 76 import jdk.vm.ci.code.Register; 77 import jdk.vm.ci.code.RegisterConfig; 78 import jdk.vm.ci.code.StackSlot; 79 import jdk.vm.ci.hotspot.HotSpotCallingConventionType; 80 import jdk.vm.ci.hotspot.HotSpotSentinelConstant; 81 import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig; 82 import jdk.vm.ci.meta.JavaKind; 83 import jdk.vm.ci.meta.JavaType; 84 import jdk.vm.ci.meta.ResolvedJavaMethod; 85 86 /** 87 * HotSpot AArch64 specific backend. 88 */ 89 public class AArch64HotSpotBackend extends HotSpotHostBackend { 90 91 public AArch64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { 92 super(config, runtime, providers); 93 } 94 95 @Override 96 public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { 97 RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; 98 return new AArch64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); 99 } 100 101 @Override 102 public FrameMap newFrameMap(RegisterConfig registerConfig) { 103 return new AArch64FrameMap(getCodeCache(), registerConfig, this); 104 } 105 106 @Override 107 public LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes) { 108 return new AArch64HotSpotLIRGenerator(getProviders(), config, lirGenRes); 109 } 110 111 @Override 112 public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) { 113 return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods())); 114 } 115 116 @Override 117 public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { 118 return new AArch64HotSpotNodeLIRBuilder(graph, lirGen, new AArch64NodeMatchRules(lirGen)); 119 } 120 121 @Override 122 protected void bangStackWithOffset(CompilationResultBuilder crb, int bangOffset) { 123 AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; 124 try (ScratchRegister sc = masm.getScratchRegister()) { 125 Register scratch = sc.getRegister(); 126 AArch64Address address = masm.makeAddress(sp, -bangOffset, scratch, 8, /* allowOverwrite */false); 127 masm.str(64, zr, address); 128 } 129 } 130 131 private class HotSpotFrameContext implements FrameContext { 132 final boolean isStub; 133 202 if (frameSize < 1 << 12) { 203 masm.add(64, sp, sp, totalFrameSize - 2 * wordSize); 204 } else { 205 masm.mov(rscratch1, totalFrameSize - 2 * wordSize); 206 masm.add(64, sp, sp, rscratch1); 207 } 208 masm.ldp(64, fp, lr, AArch64Address.createPostIndexedImmediateAddress(sp, 2)); 209 } 210 } 211 212 } 213 214 @Override 215 public boolean hasFrame() { 216 return true; 217 } 218 219 } 220 221 @Override 222 protected Assembler createAssembler(FrameMap frameMap) { 223 return new AArch64MacroAssembler(getTarget()); 224 } 225 226 @Override 227 public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { 228 HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen; 229 LIR lir = gen.getLIR(); 230 assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; 231 232 Stub stub = gen.getStub(); 233 Assembler masm = createAssembler(frameMap); 234 HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); 235 236 DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); 237 CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), lir.getDebug(), compilationResult, 238 Register.None); 239 crb.setTotalFrameSize(frameMap.totalFrameSize()); 240 crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); 241 StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); 242 if (deoptimizationRescueSlot != null && stub == null) { 243 crb.compilationResult.setCustomStackAreaOffset(deoptimizationRescueSlot); 244 } 245 246 if (stub != null) { 247 EconomicSet<Register> destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); 248 updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); 249 } 250 return crb; 251 } 252 253 @Override 254 public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { 255 AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; 256 FrameMap frameMap = crb.frameMap; 257 RegisterConfig regConfig = frameMap.getRegisterConfig(); 258 Label verifiedStub = new Label(); 259 260 emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub); 261 emitCodeBody(crb, lir, masm); 262 emitCodeSuffix(crb, masm, frameMap); 263 } 264 265 private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, AArch64MacroAssembler masm, RegisterConfig regConfig, Label verifiedStub) { 266 HotSpotProviders providers = getProviders(); 267 if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { 268 crb.recordMark(config.MARKID_UNVERIFIED_ENTRY); 269 CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, this); 270 // See definition of IC_Klass in c1_LIRAssembler_aarch64.cpp 271 // equal to scratch(1) careful! 272 Register inlineCacheKlass = AArch64HotSpotRegisterConfig.inlineCacheRegister; 273 Register receiver = asRegister(cc.getArgument(0)); 274 int transferSize = config.useCompressedClassPointers ? 4 : 8; 275 AArch64Address klassAddress = masm.makeAddress(receiver, config.hubOffset, transferSize); 276 277 // Are r10 and r11 available scratch registers here? One would hope so. 278 Register klass = r10; 279 if (config.useCompressedClassPointers) { | 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 */ 23 24 25 package org.graalvm.compiler.hotspot.aarch64; 26 27 import static java.lang.reflect.Modifier.isStatic; 28 import static jdk.vm.ci.aarch64.AArch64.lr; 29 import static jdk.vm.ci.aarch64.AArch64.r10; 30 import static jdk.vm.ci.aarch64.AArch64.sp; 31 import static jdk.vm.ci.aarch64.AArch64.zr; 32 import static jdk.vm.ci.code.ValueUtil.asRegister; 33 import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; 34 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 35 import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; 36 37 import jdk.internal.vm.compiler.collections.EconomicSet; 38 import org.graalvm.compiler.asm.Assembler; 39 import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException; 40 import org.graalvm.compiler.asm.Label; 41 import org.graalvm.compiler.asm.aarch64.AArch64Address; 42 import org.graalvm.compiler.asm.aarch64.AArch64Assembler; 43 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; 44 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; 45 import org.graalvm.compiler.code.CompilationResult; 46 import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; 47 import org.graalvm.compiler.core.common.CompilationIdentifier; 48 import org.graalvm.compiler.core.common.LIRKind; 49 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; 50 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 51 import org.graalvm.compiler.core.gen.LIRGenerationProvider; 52 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 53 import org.graalvm.compiler.hotspot.HotSpotDataBuilder; 54 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 55 import org.graalvm.compiler.hotspot.HotSpotHostBackend; 56 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; 57 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; 58 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; 59 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 60 import org.graalvm.compiler.hotspot.stubs.Stub; 61 import org.graalvm.compiler.lir.LIR; 62 import org.graalvm.compiler.lir.aarch64.AArch64Call; 63 import org.graalvm.compiler.lir.aarch64.AArch64FrameMap; 64 import org.graalvm.compiler.lir.aarch64.AArch64FrameMapBuilder; 65 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 66 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; 67 import org.graalvm.compiler.lir.asm.DataBuilder; 68 import org.graalvm.compiler.lir.asm.FrameContext; 69 import org.graalvm.compiler.lir.framemap.FrameMap; 70 import org.graalvm.compiler.lir.framemap.FrameMapBuilder; 71 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 72 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 73 import org.graalvm.compiler.nodes.StructuredGraph; 74 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 75 76 import jdk.vm.ci.aarch64.AArch64Kind; 77 import jdk.vm.ci.code.CallingConvention; 78 import jdk.vm.ci.code.Register; 79 import jdk.vm.ci.code.RegisterConfig; 80 import jdk.vm.ci.code.StackSlot; 81 import jdk.vm.ci.hotspot.HotSpotCallingConventionType; 82 import jdk.vm.ci.hotspot.HotSpotSentinelConstant; 83 import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig; 84 import jdk.vm.ci.meta.JavaKind; 85 import jdk.vm.ci.meta.JavaType; 86 import jdk.vm.ci.meta.ResolvedJavaMethod; 87 88 /** 89 * HotSpot AArch64 specific backend. 90 */ 91 public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider { 92 93 public AArch64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { 94 super(config, runtime, providers); 95 } 96 97 private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { 98 RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; 99 FrameMap frameMap = new AArch64FrameMap(getCodeCache(), registerConfigNonNull, this); 100 return new AArch64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull); 101 } 102 103 @Override 104 public LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes) { 105 return new AArch64HotSpotLIRGenerator(getProviders(), config, lirGenRes); 106 } 107 108 @Override 109 public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) { 110 return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub, 111 config.requiresReservedStackCheck(graph.getMethods())); 112 } 113 114 @Override 115 public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { 116 return new AArch64HotSpotNodeLIRBuilder(graph, lirGen, new AArch64NodeMatchRules(lirGen)); 117 } 118 119 @Override 120 protected void bangStackWithOffset(CompilationResultBuilder crb, int bangOffset) { 121 AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; 122 try (ScratchRegister sc = masm.getScratchRegister()) { 123 Register scratch = sc.getRegister(); 124 AArch64Address address = masm.makeAddress(sp, -bangOffset, scratch, 8, /* allowOverwrite */false); 125 masm.str(64, zr, address); 126 } 127 } 128 129 private class HotSpotFrameContext implements FrameContext { 130 final boolean isStub; 131 200 if (frameSize < 1 << 12) { 201 masm.add(64, sp, sp, totalFrameSize - 2 * wordSize); 202 } else { 203 masm.mov(rscratch1, totalFrameSize - 2 * wordSize); 204 masm.add(64, sp, sp, rscratch1); 205 } 206 masm.ldp(64, fp, lr, AArch64Address.createPostIndexedImmediateAddress(sp, 2)); 207 } 208 } 209 210 } 211 212 @Override 213 public boolean hasFrame() { 214 return true; 215 } 216 217 } 218 219 @Override 220 public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { 221 HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen; 222 LIR lir = gen.getLIR(); 223 assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; 224 225 Stub stub = gen.getStub(); 226 Assembler masm = new AArch64MacroAssembler(getTarget()); 227 HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); 228 229 DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); 230 CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), lir.getDebug(), compilationResult, 231 Register.None); 232 crb.setTotalFrameSize(frameMap.totalFrameSize()); 233 crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); 234 StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); 235 if (deoptimizationRescueSlot != null && stub == null) { 236 crb.compilationResult.setCustomStackAreaOffset(deoptimizationRescueSlot); 237 } 238 239 if (stub != null) { 240 EconomicSet<Register> destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); 241 updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); 242 } 243 return crb; 244 } 245 246 @Override 247 public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { 248 Label verifiedStub = new Label(); 249 crb.buildLabelOffsets(lir); 250 try { 251 emitCode(crb, lir, installedCodeOwner, verifiedStub); 252 } catch (BranchTargetOutOfBoundsException e) { 253 // A branch estimation was wrong, now retry with conservative label ranges, this 254 // should always work 255 crb.setConservativeLabelRanges(); 256 crb.resetForEmittingCode(); 257 lir.resetLabels(); 258 verifiedStub.reset(); 259 emitCode(crb, lir, installedCodeOwner, verifiedStub); 260 } 261 } 262 263 private void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner, Label verifiedStub) { 264 AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; 265 FrameMap frameMap = crb.frameMap; 266 RegisterConfig regConfig = frameMap.getRegisterConfig(); 267 emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub); 268 emitCodeBody(crb, lir, masm); 269 emitCodeSuffix(crb, masm, frameMap); 270 } 271 272 private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, AArch64MacroAssembler masm, RegisterConfig regConfig, Label verifiedStub) { 273 HotSpotProviders providers = getProviders(); 274 if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { 275 crb.recordMark(config.MARKID_UNVERIFIED_ENTRY); 276 CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, this); 277 // See definition of IC_Klass in c1_LIRAssembler_aarch64.cpp 278 // equal to scratch(1) careful! 279 Register inlineCacheKlass = AArch64HotSpotRegisterConfig.inlineCacheRegister; 280 Register receiver = asRegister(cc.getArgument(0)); 281 int transferSize = config.useCompressedClassPointers ? 4 : 8; 282 AArch64Address klassAddress = masm.makeAddress(receiver, config.hubOffset, transferSize); 283 284 // Are r10 and r11 available scratch registers here? One would hope so. 285 Register klass = r10; 286 if (config.useCompressedClassPointers) { |