1 /* 2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018, Red Hat Inc. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 26 27 package org.graalvm.compiler.hotspot.aarch64; 28 29 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 30 import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; 31 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE; 32 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; 33 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; 34 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; 35 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.INITIALIZE; 36 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS; 37 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE; 38 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; 39 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; 40 41 import java.util.function.Function; 42 43 import org.graalvm.compiler.asm.Label; 44 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; 45 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; 46 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; 47 import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator; 48 import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; 49 import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; 50 import org.graalvm.compiler.core.common.CompressEncoding; 51 import org.graalvm.compiler.core.common.LIRKind; 52 import org.graalvm.compiler.core.common.calc.Condition; 53 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; 54 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 55 import org.graalvm.compiler.core.common.spi.LIRKindTool; 56 import org.graalvm.compiler.debug.GraalError; 57 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 58 import org.graalvm.compiler.hotspot.HotSpotBackend; 59 import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; 60 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; 61 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; 62 import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; 63 import org.graalvm.compiler.hotspot.HotSpotLockStack; 64 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; 65 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 66 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; 67 import org.graalvm.compiler.hotspot.stubs.Stub; 68 import org.graalvm.compiler.lir.LIRFrameState; 69 import org.graalvm.compiler.lir.LIRInstruction; 70 import org.graalvm.compiler.lir.LabelRef; 71 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; 72 import org.graalvm.compiler.lir.SwitchStrategy; 73 import org.graalvm.compiler.lir.Variable; 74 import org.graalvm.compiler.lir.VirtualStackSlot; 75 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; 76 import org.graalvm.compiler.lir.aarch64.AArch64CCall; 77 import org.graalvm.compiler.lir.aarch64.AArch64Call; 78 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; 79 import org.graalvm.compiler.lir.aarch64.AArch64FrameMapBuilder; 80 import org.graalvm.compiler.lir.aarch64.AArch64Move; 81 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; 82 import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp; 83 import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp; 84 import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp; 85 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 86 import org.graalvm.compiler.options.OptionValues; 87 88 import jdk.vm.ci.aarch64.AArch64; 89 import jdk.vm.ci.aarch64.AArch64Kind; 90 import jdk.vm.ci.code.CallingConvention; 91 import jdk.vm.ci.code.Register; 92 import jdk.vm.ci.code.RegisterValue; 93 import jdk.vm.ci.code.StackSlot; 94 import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; 95 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; 96 import jdk.vm.ci.hotspot.HotSpotObjectConstant; 97 import jdk.vm.ci.meta.AllocatableValue; 98 import jdk.vm.ci.meta.Constant; 99 import jdk.vm.ci.meta.DeoptimizationAction; 100 import jdk.vm.ci.meta.DeoptimizationReason; 101 import jdk.vm.ci.meta.JavaConstant; 102 import jdk.vm.ci.meta.JavaKind; 103 import jdk.vm.ci.meta.PlatformKind; 104 import jdk.vm.ci.meta.SpeculationLog; 105 import jdk.vm.ci.meta.Value; 106 107 /** 108 * LIR generator specialized for AArch64 HotSpot. 109 */ 110 public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements HotSpotLIRGenerator { 111 112 final GraalHotSpotVMConfig config; 113 private HotSpotDebugInfoBuilder debugInfoBuilder; 114 115 protected AArch64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { 116 this(new AArch64LIRKindTool(), new AArch64ArithmeticLIRGenerator(null), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); 117 } 118 119 protected AArch64HotSpotLIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, 120 LIRGenerationResult lirGenRes) { 121 super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); 122 this.config = config; 123 } 124 125 @Override 126 public HotSpotProviders getProviders() { 127 return (HotSpotProviders) super.getProviders(); 128 } 129 130 @Override 131 public boolean needOnlyOopMaps() { 132 // Stubs only need oop maps 133 return getResult().getStub() != null; 134 } 135 136 private LIRFrameState currentRuntimeCallInfo; 137 138 @Override 139 protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { 140 currentRuntimeCallInfo = info; 141 if (AArch64Call.isNearCall(linkage)) { 142 append(new AArch64Call.DirectNearForeignCallOp(linkage, result, arguments, temps, info, label)); 143 } else { 144 append(new AArch64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info, label)); 145 } 146 } 147 148 @Override 149 public void emitTailcall(Value[] args, Value address) { 150 throw GraalError.unimplemented(); 151 } 152 153 @Override 154 public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args) { 155 Value[] argLocations = new Value[args.length]; 156 getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention); 157 for (int i = 0; i < args.length; i++) { 158 Value arg = args[i]; 159 AllocatableValue loc = nativeCallingConvention.getArgument(i); 160 emitMove(loc, arg); 161 argLocations[i] = loc; 162 } 163 Value ptr = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(address)); 164 append(new AArch64CCall(nativeCallingConvention.getReturn(), ptr, argLocations)); 165 } 166 167 /** 168 * @param savedRegisters the registers saved by this operation which may be subject to pruning 169 * @param savedRegisterLocations the slots to which the registers are saved 170 * @param supportsRemove determines if registers can be pruned 171 */ 172 protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { 173 AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); 174 append(save); 175 return save; 176 } 177 178 /** 179 * Allocate a stack slot for saving a register. 180 */ 181 protected VirtualStackSlot allocateSaveRegisterLocation(Register register) { 182 PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory()); 183 if (kind.getVectorLength() > 1) { 184 // we don't use vector registers, so there is no need to save them 185 kind = AArch64Kind.QWORD; 186 } 187 return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); 188 } 189 190 /** 191 * Adds a node to the graph that saves all allocatable registers to the stack. 192 * 193 * @param supportsRemove determines if registers can be pruned 194 * @return the register save node 195 */ 196 private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) { 197 AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; 198 for (int i = 0; i < savedRegisters.length; i++) { 199 savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]); 200 } 201 return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); 202 } 203 204 protected void emitRestoreRegisters(AArch64SaveRegistersOp save) { 205 append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save)); 206 } 207 208 @Override 209 public VirtualStackSlot getLockSlot(int lockDepth) { 210 return getLockStack().makeLockSlot(lockDepth); 211 } 212 213 private HotSpotLockStack getLockStack() { 214 assert debugInfoBuilder != null && debugInfoBuilder.lockStack() != null; 215 return debugInfoBuilder.lockStack(); 216 } 217 218 @Override 219 public void emitCompareBranch(PlatformKind cmpKind, Value x, Value y, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, 220 double trueDestinationProbability) { 221 Value localX = x; 222 Value localY = y; 223 if (localX instanceof HotSpotObjectConstant) { 224 localX = load(localX); 225 } 226 if (localY instanceof HotSpotObjectConstant) { 227 localY = load(localY); 228 } 229 super.emitCompareBranch(cmpKind, localX, localY, cond, unorderedIsTrue, trueDestination, falseDestination, trueDestinationProbability); 230 } 231 232 @Override 233 protected boolean emitCompare(PlatformKind cmpKind, Value a, Value b, Condition condition, boolean unorderedIsTrue) { 234 Value localA = a; 235 Value localB = b; 236 if (isConstantValue(a)) { 237 Constant c = asConstant(a); 238 if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { 239 localA = AArch64.zr.asValue(LIRKind.value(AArch64Kind.DWORD)); 240 } else if (c instanceof HotSpotObjectConstant) { 241 localA = load(localA); 242 } 243 } 244 if (isConstantValue(b)) { 245 Constant c = asConstant(b); 246 if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { 247 localB = AArch64.zr.asValue(LIRKind.value(AArch64Kind.DWORD)); 248 } else if (c instanceof HotSpotObjectConstant) { 249 localB = load(localB); 250 } 251 } 252 return super.emitCompare(cmpKind, localA, localB, condition, unorderedIsTrue); 253 } 254 255 @Override 256 public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { 257 LIRKind inputKind = pointer.getValueKind(LIRKind.class); 258 LIRKindTool lirKindTool = getLIRKindTool(); 259 assert inputKind.getPlatformKind() == AArch64Kind.QWORD; 260 if (inputKind.isReference(0)) { 261 // oop 262 Variable result = newVariable(LIRKind.compressedReference(AArch64Kind.DWORD)); 263 append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); 264 return result; 265 } else { 266 // metaspace pointer 267 Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); 268 AllocatableValue base = Value.ILLEGAL; 269 OptionValues options = getResult().getLIR().getOptions(); 270 if (encoding.hasBase() || GeneratePIC.getValue(options)) { 271 if (GeneratePIC.getValue(options)) { 272 Variable baseAddress = newVariable(lirKindTool.getWordKind()); 273 AArch64HotSpotMove.BaseMove move = new AArch64HotSpotMove.BaseMove(baseAddress, config); 274 append(move); 275 base = baseAddress; 276 } else { 277 base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); 278 } 279 } 280 append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); 281 return result; 282 } 283 } 284 285 @Override 286 public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) { 287 LIRKind inputKind = pointer.getValueKind(LIRKind.class); 288 assert inputKind.getPlatformKind() == AArch64Kind.DWORD; 289 if (inputKind.isReference(0)) { 290 // oop 291 Variable result = newVariable(LIRKind.reference(AArch64Kind.QWORD)); 292 append(new AArch64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); 293 return result; 294 } else { 295 // metaspace pointer 296 Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); 297 AllocatableValue base = Value.ILLEGAL; 298 OptionValues options = getResult().getLIR().getOptions(); 299 if (encoding.hasBase() || GeneratePIC.getValue(options)) { 300 if (GeneratePIC.getValue(options)) { 301 Variable baseAddress = newVariable(LIRKind.value(AArch64Kind.QWORD)); 302 AArch64HotSpotMove.BaseMove move = new AArch64HotSpotMove.BaseMove(baseAddress, config); 303 append(move); 304 base = baseAddress; 305 } else { 306 base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); 307 } 308 } 309 append(new AArch64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); 310 return result; 311 } 312 } 313 314 @Override 315 public void emitNullCheck(Value address, LIRFrameState state) { 316 if (address.getValueKind().getPlatformKind() == AArch64Kind.DWORD) { 317 CompressEncoding encoding = config.getOopEncoding(); 318 Value uncompressed = emitUncompress(address, encoding, false); 319 append(new AArch64Move.NullCheckOp(asAddressValue(uncompressed), state)); 320 } else { 321 super.emitNullCheck(address, state); 322 } 323 } 324 325 @Override 326 public void emitPrefetchAllocate(Value address) { 327 append(new AArch64PrefetchOp(asAddressValue(address), PrefetchMode.PSTL1KEEP)); 328 } 329 330 @Override 331 public void beforeRegisterAllocation() { 332 super.beforeRegisterAllocation(); 333 boolean hasDebugInfo = getResult().getLIR().hasDebugInfo(); 334 if (hasDebugInfo) { 335 getResult().setDeoptimizationRescueSlot(((AArch64FrameMapBuilder) getResult().getFrameMapBuilder()).allocateDeoptimizationRescueSlot()); 336 } 337 338 getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize()); 339 } 340 341 private Label label; 342 343 @Override 344 public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { 345 HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; 346 boolean destroysRegisters = hotspotLinkage.destroysRegisters(); 347 348 AArch64SaveRegistersOp save = null; 349 Stub stub = getStub(); 350 if (destroysRegisters) { 351 if (stub != null && stub.preservesRegisters()) { 352 Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray(); 353 save = emitSaveAllRegisters(savedRegisters, true); 354 } 355 } 356 357 Variable result; 358 LIRFrameState debugInfo = null; 359 if (hotspotLinkage.needsDebugInfo()) { 360 debugInfo = state; 361 assert debugInfo != null || getStub() != null; 362 } 363 364 if (destroysRegisters || hotspotLinkage.needsJavaFrameAnchor()) { 365 HotSpotRegistersProvider registers = getProviders().getRegisters(); 366 Register thread = registers.getThreadRegister(); 367 Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind())); 368 369 // We need a label for the return address. 370 label = new Label(); 371 372 append(new AArch64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), thread, scratch, label)); 373 result = super.emitForeignCall(hotspotLinkage, debugInfo, args); 374 append(new AArch64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), thread, label)); 375 376 // Clear it out so it's not being reused later. 377 label = null; 378 } else { 379 result = super.emitForeignCall(hotspotLinkage, debugInfo, args); 380 } 381 382 if (destroysRegisters) { 383 if (stub != null) { 384 if (stub.preservesRegisters()) { 385 HotSpotLIRGenerationResult generationResult = getResult(); 386 LIRFrameState key = currentRuntimeCallInfo; 387 if (key == null) { 388 key = LIRFrameState.NO_STATE; 389 } 390 assert !generationResult.getCalleeSaveInfo().containsKey(key); 391 generationResult.getCalleeSaveInfo().put(key, save); 392 emitRestoreRegisters(save); 393 } 394 } 395 } 396 397 return result; 398 } 399 400 @Override 401 public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { 402 Value actionAndReason = emitJavaConstant(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0)); 403 Value speculation = emitJavaConstant(getMetaAccess().encodeSpeculation(SpeculationLog.NO_SPECULATION)); 404 moveDeoptValuesToThread(actionAndReason, speculation); 405 append(new AArch64HotSpotDeoptimizeCallerOp(config)); 406 } 407 408 @Override 409 public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state) { 410 moveDeoptValuesToThread(actionAndReason, failedSpeculation); 411 append(new AArch64HotSpotDeoptimizeOp(state)); 412 } 413 414 private void moveDeoptValuesToThread(Value actionAndReason, Value speculation) { 415 moveValueToThread(actionAndReason, config.pendingDeoptimizationOffset); 416 moveValueToThread(speculation, config.pendingFailedSpeculationOffset); 417 } 418 419 private void moveValueToThread(Value value, int offset) { 420 LIRKind wordKind = LIRKind.value(target().arch.getWordKind()); 421 RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind); 422 final int transferSize = value.getValueKind().getPlatformKind().getSizeInBytes(); 423 AArch64AddressValue address = new AArch64AddressValue(value.getValueKind(), thread, Value.ILLEGAL, offset, transferSize, AddressingMode.IMMEDIATE_SCALED); 424 append(new StoreOp((AArch64Kind) value.getPlatformKind(), address, loadReg(value), null)); 425 } 426 427 @Override 428 public void emitUnwind(Value exception) { 429 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER); 430 CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); 431 assert outgoingCc.getArgumentCount() == 2; 432 RegisterValue exceptionParameter = (RegisterValue) outgoingCc.getArgument(0); 433 emitMove(exceptionParameter, exception); 434 append(new AArch64HotSpotUnwindOp(config, exceptionParameter)); 435 } 436 437 @Override 438 public Value emitLoadObjectAddress(Constant constant) { 439 HotSpotObjectConstant objectConstant = (HotSpotObjectConstant) constant; 440 LIRKind kind = objectConstant.isCompressed() ? getLIRKindTool().getNarrowOopKind() : getLIRKindTool().getObjectKind(); 441 Variable result = newVariable(kind); 442 append(new AArch64HotSpotLoadAddressOp(result, constant, HotSpotConstantLoadAction.RESOLVE)); 443 return result; 444 } 445 446 @Override 447 public Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) { 448 HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; 449 LIRKind kind = metaspaceConstant.isCompressed() ? getLIRKindTool().getNarrowPointerKind() : getLIRKindTool().getWordKind(); 450 Variable result = newVariable(kind); 451 append(new AArch64HotSpotLoadAddressOp(result, constant, action)); 452 return result; 453 } 454 455 private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, Object[] notes, Constant[] constants, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { 456 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(foreignCall); 457 append(new AArch64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); 458 AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); 459 return emitMove(result); 460 } 461 462 private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { 463 Constant[] constants = new Constant[]{constant}; 464 Object[] notes = new Object[]{action}; 465 return emitConstantRetrieval(foreignCall, notes, constants, constantDescriptions, frameState); 466 } 467 468 @Override 469 public Value emitResolveDynamicInvoke(Constant appendix, LIRFrameState frameState) { 470 AllocatableValue[] constantDescriptions = new AllocatableValue[0]; 471 return emitConstantRetrieval(RESOLVE_DYNAMIC_INVOKE, INITIALIZE, appendix, constantDescriptions, frameState); 472 } 473 474 @Override 475 public Value emitLoadConfigValue(int markId, LIRKind kind) { 476 Variable result = newVariable(kind); 477 append(new AArch64HotSpotLoadConfigValueOp(markId, result)); 478 return result; 479 } 480 481 private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, Value constantDescription, LIRFrameState frameState) { 482 AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(constantDescription)}; 483 return emitConstantRetrieval(foreignCall, action, constant, constantDescriptions, frameState); 484 } 485 486 @Override 487 public Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { 488 return emitConstantRetrieval(RESOLVE_STRING_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); 489 } 490 491 @Override 492 public Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { 493 return emitConstantRetrieval(RESOLVE_KLASS_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); 494 } 495 496 @Override 497 public void emitReturn(JavaKind kind, Value input) { 498 AllocatableValue operand = Value.ILLEGAL; 499 if (input != null) { 500 operand = resultOperandFor(kind, input.getValueKind()); 501 emitMove(operand, input); 502 } 503 Register thread = getProviders().getRegisters().getThreadRegister(); 504 append(new AArch64HotSpotReturnOp(operand, getStub() != null, config, thread, getResult().requiresReservedStackAccessCheck())); 505 } 506 507 @Override 508 public Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { 509 return emitConstantRetrieval(INITIALIZE_KLASS_BY_SYMBOL, INITIALIZE, constant, constantDescription, frameState); 510 } 511 512 @Override 513 public Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) { 514 AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(klassHint), asAllocatable(methodDescription)}; 515 return emitConstantRetrieval(RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, LOAD_COUNTERS, method, constantDescriptions, frameState); 516 } 517 518 /** 519 * Gets the {@link Stub} this generator is generating code for or {@code null} if a stub is not 520 * being generated. 521 */ 522 public Stub getStub() { 523 return getResult().getStub(); 524 } 525 526 @Override 527 public HotSpotLIRGenerationResult getResult() { 528 return ((HotSpotLIRGenerationResult) super.getResult()); 529 } 530 531 @Override 532 protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue, 533 Function<Condition, ConditionFlag> converter) { 534 return new AArch64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, scratchValue, converter); 535 } 536 537 public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) { 538 this.debugInfoBuilder = debugInfoBuilder; 539 } 540 541 @Override 542 public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) { 543 throw GraalError.unimplemented(); 544 } 545 546 @Override 547 public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) { 548 throw GraalError.unimplemented(); 549 } 550 }