AMD64HotSpotLIRGenerator.java revision 12968:4d8a004e5c6d
1/* 2 * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. 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 */ 23package org.graalvm.compiler.hotspot.amd64; 24 25import static jdk.vm.ci.amd64.AMD64.rbp; 26import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 27import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; 28import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; 29import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; 30import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; 31 32import java.util.ArrayList; 33import java.util.List; 34 35import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; 36import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; 37import org.graalvm.compiler.core.amd64.AMD64LIRGenerator; 38import org.graalvm.compiler.core.amd64.AMD64MoveFactoryBase.BackupSlotProvider; 39import org.graalvm.compiler.core.common.CompressEncoding; 40import org.graalvm.compiler.core.common.LIRKind; 41import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 42import org.graalvm.compiler.core.common.spi.LIRKindTool; 43import org.graalvm.compiler.debug.Debug; 44import org.graalvm.compiler.debug.GraalError; 45import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 46import org.graalvm.compiler.hotspot.HotSpotBackend; 47import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; 48import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; 49import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; 50import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; 51import org.graalvm.compiler.hotspot.HotSpotLockStack; 52import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; 53import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; 54import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 55import org.graalvm.compiler.hotspot.nodes.type.HotSpotLIRKindTool; 56import org.graalvm.compiler.hotspot.stubs.Stub; 57import org.graalvm.compiler.lir.LIR; 58import org.graalvm.compiler.lir.LIRFrameState; 59import org.graalvm.compiler.lir.LIRInstruction; 60import org.graalvm.compiler.lir.LIRInstructionClass; 61import org.graalvm.compiler.lir.LabelRef; 62import org.graalvm.compiler.lir.StandardOp.NoOp; 63import org.graalvm.compiler.lir.SwitchStrategy; 64import org.graalvm.compiler.lir.Variable; 65import org.graalvm.compiler.lir.VirtualStackSlot; 66import org.graalvm.compiler.lir.amd64.AMD64AddressValue; 67import org.graalvm.compiler.lir.amd64.AMD64CCall; 68import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp; 69import org.graalvm.compiler.lir.amd64.AMD64FrameMapBuilder; 70import org.graalvm.compiler.lir.amd64.AMD64Move; 71import org.graalvm.compiler.lir.amd64.AMD64Move.MoveFromRegOp; 72import org.graalvm.compiler.lir.amd64.AMD64PrefetchOp; 73import org.graalvm.compiler.lir.amd64.AMD64ReadTimestampCounter; 74import org.graalvm.compiler.lir.amd64.AMD64RestoreRegistersOp; 75import org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp; 76import org.graalvm.compiler.lir.amd64.AMD64VZeroUpper; 77import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 78import org.graalvm.compiler.lir.framemap.FrameMapBuilder; 79import org.graalvm.compiler.lir.gen.LIRGenerationResult; 80import org.graalvm.compiler.options.OptionValues; 81 82import jdk.vm.ci.amd64.AMD64; 83import jdk.vm.ci.amd64.AMD64Kind; 84import jdk.vm.ci.code.CallingConvention; 85import jdk.vm.ci.code.Register; 86import jdk.vm.ci.code.RegisterConfig; 87import jdk.vm.ci.code.RegisterValue; 88import jdk.vm.ci.code.StackSlot; 89import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; 90import jdk.vm.ci.hotspot.HotSpotObjectConstant; 91import jdk.vm.ci.meta.AllocatableValue; 92import jdk.vm.ci.meta.Constant; 93import jdk.vm.ci.meta.DeoptimizationAction; 94import jdk.vm.ci.meta.DeoptimizationReason; 95import jdk.vm.ci.meta.JavaConstant; 96import jdk.vm.ci.meta.JavaKind; 97import jdk.vm.ci.meta.PlatformKind; 98import jdk.vm.ci.meta.PrimitiveConstant; 99import jdk.vm.ci.meta.Value; 100 101/** 102 * LIR generator specialized for AMD64 HotSpot. 103 */ 104public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator { 105 106 final GraalHotSpotVMConfig config; 107 private HotSpotDebugInfoBuilder debugInfoBuilder; 108 109 protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { 110 this(providers, config, lirGenRes, new BackupSlotProvider(lirGenRes.getFrameMapBuilder())); 111 } 112 113 private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) { 114 this(new AMD64HotSpotLIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); 115 } 116 117 protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, 118 LIRGenerationResult lirGenRes) { 119 super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); 120 assert config.basicLockSize == 8; 121 this.config = config; 122 } 123 124 @Override 125 public HotSpotProviders getProviders() { 126 return (HotSpotProviders) super.getProviders(); 127 } 128 129 /** 130 * Utility for emitting the instruction to save RBP. 131 */ 132 class SaveRbp { 133 134 final NoOp placeholder; 135 136 /** 137 * The slot reserved for saving RBP. 138 */ 139 final StackSlot reservedSlot; 140 141 SaveRbp(NoOp placeholder) { 142 this.placeholder = placeholder; 143 AMD64FrameMapBuilder frameMapBuilder = (AMD64FrameMapBuilder) getResult().getFrameMapBuilder(); 144 this.reservedSlot = frameMapBuilder.allocateRBPSpillSlot(); 145 } 146 147 /** 148 * Replaces this operation with the appropriate move for saving rbp. 149 * 150 * @param useStack specifies if rbp must be saved to the stack 151 */ 152 public AllocatableValue finalize(boolean useStack) { 153 AllocatableValue dst; 154 if (useStack) { 155 dst = reservedSlot; 156 } else { 157 ((AMD64FrameMapBuilder) getResult().getFrameMapBuilder()).freeRBPSpillSlot(); 158 dst = newVariable(LIRKind.value(AMD64Kind.QWORD)); 159 } 160 161 placeholder.replace(getResult().getLIR(), new MoveFromRegOp(AMD64Kind.QWORD, dst, rbp.asValue(LIRKind.value(AMD64Kind.QWORD)))); 162 return dst; 163 } 164 } 165 166 private SaveRbp saveRbp; 167 168 protected void emitSaveRbp() { 169 NoOp placeholder = new NoOp(getCurrentBlock(), getResult().getLIR().getLIRforBlock(getCurrentBlock()).size()); 170 append(placeholder); 171 saveRbp = new SaveRbp(placeholder); 172 } 173 174 protected SaveRbp getSaveRbp() { 175 return saveRbp; 176 } 177 178 /** 179 * Helper instruction to reserve a stack slot for the whole method. Note that the actual users 180 * of the stack slot might be inserted after stack slot allocation. This dummy instruction 181 * ensures that the stack slot is alive and gets a real stack slot assigned. 182 */ 183 private static final class RescueSlotDummyOp extends LIRInstruction { 184 public static final LIRInstructionClass<RescueSlotDummyOp> TYPE = LIRInstructionClass.create(RescueSlotDummyOp.class); 185 186 @Alive({OperandFlag.STACK, OperandFlag.UNINITIALIZED}) private AllocatableValue slot; 187 188 RescueSlotDummyOp(FrameMapBuilder frameMapBuilder, LIRKind kind) { 189 super(TYPE); 190 slot = frameMapBuilder.allocateSpillSlot(kind); 191 } 192 193 public AllocatableValue getSlot() { 194 return slot; 195 } 196 197 @Override 198 public void emitCode(CompilationResultBuilder crb) { 199 } 200 } 201 202 private RescueSlotDummyOp rescueSlotOp; 203 204 private AllocatableValue getOrInitRescueSlot() { 205 RescueSlotDummyOp op = getOrInitRescueSlotOp(); 206 return op.getSlot(); 207 } 208 209 private RescueSlotDummyOp getOrInitRescueSlotOp() { 210 if (rescueSlotOp == null) { 211 // create dummy instruction to keep the rescue slot alive 212 rescueSlotOp = new RescueSlotDummyOp(getResult().getFrameMapBuilder(), getLIRKindTool().getWordKind()); 213 } 214 return rescueSlotOp; 215 } 216 217 /** 218 * List of epilogue operations that need to restore RBP. 219 */ 220 List<AMD64HotSpotRestoreRbpOp> epilogueOps = new ArrayList<>(2); 221 222 @Override 223 public <I extends LIRInstruction> I append(I op) { 224 I ret = super.append(op); 225 if (op instanceof AMD64HotSpotRestoreRbpOp) { 226 epilogueOps.add((AMD64HotSpotRestoreRbpOp) op); 227 } 228 return ret; 229 } 230 231 @Override 232 public VirtualStackSlot getLockSlot(int lockDepth) { 233 return getLockStack().makeLockSlot(lockDepth); 234 } 235 236 private HotSpotLockStack getLockStack() { 237 assert debugInfoBuilder != null && debugInfoBuilder.lockStack() != null; 238 return debugInfoBuilder.lockStack(); 239 } 240 241 private Register findPollOnReturnScratchRegister() { 242 RegisterConfig regConfig = getProviders().getCodeCache().getRegisterConfig(); 243 for (Register r : regConfig.getAllocatableRegisters()) { 244 if (!r.equals(regConfig.getReturnRegister(JavaKind.Long)) && !r.equals(AMD64.rbp)) { 245 return r; 246 } 247 } 248 throw GraalError.shouldNotReachHere(); 249 } 250 251 private Register pollOnReturnScratchRegister; 252 253 @Override 254 public void emitReturn(JavaKind kind, Value input) { 255 AllocatableValue operand = Value.ILLEGAL; 256 if (input != null) { 257 operand = resultOperandFor(kind, input.getValueKind()); 258 emitMove(operand, input); 259 } 260 if (pollOnReturnScratchRegister == null) { 261 pollOnReturnScratchRegister = findPollOnReturnScratchRegister(); 262 } 263 append(new AMD64HotSpotReturnOp(operand, getStub() != null, pollOnReturnScratchRegister, config)); 264 } 265 266 @Override 267 public boolean needOnlyOopMaps() { 268 // Stubs only need oop maps 269 return getResult().getStub() != null; 270 } 271 272 private LIRFrameState currentRuntimeCallInfo; 273 274 @Override 275 protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { 276 currentRuntimeCallInfo = info; 277 HotSpotForeignCallLinkage hsLinkage = (HotSpotForeignCallLinkage) linkage; 278 AMD64 arch = (AMD64) target().arch; 279 if (arch.getFeatures().contains(AMD64.CPUFeature.AVX) && hsLinkage.mayContainFP() && !hsLinkage.isCompiledStub()) { 280 /* 281 * If the target may contain FP ops, and it is not compiled by us, we may have an 282 * AVX-SSE transition. 283 * 284 * We exclude the argument registers from the zeroing LIR instruction since it violates 285 * the LIR semantics of @Temp that values must not be live. Note that the emitted 286 * machine instruction actually zeros _all_ XMM registers which is fine since we know 287 * that their upper half is not used. 288 */ 289 append(new AMD64VZeroUpper(arguments)); 290 } 291 super.emitForeignCallOp(linkage, result, arguments, temps, info); 292 } 293 294 /** 295 * @param savedRegisters the registers saved by this operation which may be subject to pruning 296 * @param savedRegisterLocations the slots to which the registers are saved 297 * @param supportsRemove determines if registers can be pruned 298 */ 299 protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { 300 AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); 301 append(save); 302 return save; 303 } 304 305 /** 306 * Allocate a stack slot for saving a register. 307 */ 308 protected VirtualStackSlot allocateSaveRegisterLocation(Register register) { 309 PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory()); 310 if (kind.getVectorLength() > 1) { 311 // we don't use vector registers, so there is no need to save them 312 kind = AMD64Kind.DOUBLE; 313 } 314 return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); 315 } 316 317 /** 318 * Adds a node to the graph that saves all allocatable registers to the stack. 319 * 320 * @param supportsRemove determines if registers can be pruned 321 * @return the register save node 322 */ 323 private AMD64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) { 324 AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; 325 for (int i = 0; i < savedRegisters.length; i++) { 326 savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]); 327 } 328 return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); 329 } 330 331 protected void emitRestoreRegisters(AMD64SaveRegistersOp save) { 332 append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save)); 333 } 334 335 /** 336 * Gets the {@link Stub} this generator is generating code for or {@code null} if a stub is not 337 * being generated. 338 */ 339 public Stub getStub() { 340 return getResult().getStub(); 341 } 342 343 @Override 344 public HotSpotLIRGenerationResult getResult() { 345 return ((HotSpotLIRGenerationResult) super.getResult()); 346 } 347 348 public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) { 349 this.debugInfoBuilder = debugInfoBuilder; 350 } 351 352 @Override 353 public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { 354 HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; 355 boolean destroysRegisters = hotspotLinkage.destroysRegisters(); 356 357 AMD64SaveRegistersOp save = null; 358 Stub stub = getStub(); 359 if (destroysRegisters) { 360 if (stub != null && stub.preservesRegisters()) { 361 Register[] savedRegisters = getResult().getFrameMapBuilder().getRegisterConfig().getAllocatableRegisters().toArray(); 362 save = emitSaveAllRegisters(savedRegisters, true); 363 } 364 } 365 366 Variable result; 367 LIRFrameState debugInfo = null; 368 if (hotspotLinkage.needsDebugInfo()) { 369 debugInfo = state; 370 assert debugInfo != null || stub != null; 371 } 372 373 if (hotspotLinkage.needsJavaFrameAnchor()) { 374 Register thread = getProviders().getRegisters().getThreadRegister(); 375 append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); 376 result = super.emitForeignCall(hotspotLinkage, debugInfo, args); 377 append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), config.threadLastJavaPcOffset(), thread)); 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 Value emitLoadObjectAddress(Constant constant) { 402 HotSpotObjectConstant objectConstant = (HotSpotObjectConstant) constant; 403 HotSpotLIRKindTool kindTool = (HotSpotLIRKindTool) getLIRKindTool(); 404 LIRKind kind = objectConstant.isCompressed() ? kindTool.getNarrowOopKind() : kindTool.getObjectKind(); 405 Variable result = newVariable(kind); 406 append(new AMD64HotSpotLoadAddressOp(result, constant, HotSpotConstantLoadAction.RESOLVE)); 407 return result; 408 } 409 410 @Override 411 public Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) { 412 HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; 413 HotSpotLIRKindTool kindTool = (HotSpotLIRKindTool) getLIRKindTool(); 414 LIRKind kind = metaspaceConstant.isCompressed() ? kindTool.getNarrowPointerKind() : kindTool.getWordKind(); 415 Variable result = newVariable(kind); 416 append(new AMD64HotSpotLoadAddressOp(result, constant, action)); 417 return result; 418 } 419 420 @Override 421 public Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { 422 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(RESOLVE_STRING_BY_SYMBOL); 423 Constant[] constants = new Constant[]{constant}; 424 AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(constantDescription)}; 425 Object[] notes = new Object[]{HotSpotConstantLoadAction.RESOLVE}; 426 append(new AMD64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); 427 AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); 428 return emitMove(result); 429 } 430 431 @Override 432 public Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { 433 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(RESOLVE_KLASS_BY_SYMBOL); 434 Constant[] constants = new Constant[]{constant}; 435 AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(constantDescription)}; 436 Object[] notes = new Object[]{HotSpotConstantLoadAction.RESOLVE}; 437 append(new AMD64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); 438 AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); 439 return emitMove(result); 440 } 441 442 @Override 443 public Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) { 444 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS); 445 Constant[] constants = new Constant[]{method}; 446 AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(klassHint), asAllocatable(methodDescription)}; 447 Object[] notes = new Object[]{HotSpotConstantLoadAction.LOAD_COUNTERS}; 448 append(new AMD64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); 449 AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); 450 return emitMove(result); 451 452 } 453 454 @Override 455 public Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { 456 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(INITIALIZE_KLASS_BY_SYMBOL); 457 Constant[] constants = new Constant[]{constant}; 458 AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(constantDescription)}; 459 Object[] notes = new Object[]{HotSpotConstantLoadAction.INITIALIZE}; 460 append(new AMD64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); 461 AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); 462 return emitMove(result); 463 } 464 465 @Override 466 public Value emitLoadConfigValue(int markId, LIRKind kind) { 467 Variable result = newVariable(kind); 468 append(new AMD64HotSpotLoadConfigValueOp(markId, result)); 469 return result; 470 } 471 472 @Override 473 public Value emitRandomSeed() { 474 AMD64ReadTimestampCounter timestamp = new AMD64ReadTimestampCounter(); 475 append(timestamp); 476 return emitMove(timestamp.getLowResult()); 477 } 478 479 @Override 480 public void emitTailcall(Value[] args, Value address) { 481 append(new AMD64TailcallOp(args, address)); 482 } 483 484 @Override 485 public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args, int numberOfFloatingPointArguments) { 486 Value[] argLocations = new Value[args.length]; 487 getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention); 488 // TODO(mg): in case a native function uses floating point varargs, the ABI requires that 489 // RAX contains the length of the varargs 490 PrimitiveConstant intConst = JavaConstant.forInt(numberOfFloatingPointArguments); 491 AllocatableValue numberOfFloatingPointArgumentsRegister = AMD64.rax.asValue(LIRKind.value(AMD64Kind.DWORD)); 492 emitMoveConstant(numberOfFloatingPointArgumentsRegister, intConst); 493 for (int i = 0; i < args.length; i++) { 494 Value arg = args[i]; 495 AllocatableValue loc = nativeCallingConvention.getArgument(i); 496 emitMove(loc, arg); 497 argLocations[i] = loc; 498 } 499 Value ptr = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(address)); 500 append(new AMD64CCall(nativeCallingConvention.getReturn(), ptr, numberOfFloatingPointArgumentsRegister, argLocations)); 501 } 502 503 @Override 504 public void emitUnwind(Value exception) { 505 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER); 506 CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); 507 assert outgoingCc.getArgumentCount() == 2; 508 RegisterValue exceptionParameter = (RegisterValue) outgoingCc.getArgument(0); 509 emitMove(exceptionParameter, exception); 510 append(new AMD64HotSpotUnwindOp(exceptionParameter)); 511 } 512 513 private void moveDeoptValuesToThread(Value actionAndReason, Value speculation) { 514 moveValueToThread(actionAndReason, config.pendingDeoptimizationOffset); 515 moveValueToThread(speculation, config.pendingFailedSpeculationOffset); 516 } 517 518 private void moveValueToThread(Value v, int offset) { 519 LIRKind wordKind = LIRKind.value(target().arch.getWordKind()); 520 RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind); 521 AMD64AddressValue address = new AMD64AddressValue(wordKind, thread, offset); 522 arithmeticLIRGen.emitStore(v.getValueKind(), address, v, null); 523 } 524 525 @Override 526 public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { 527 moveDeoptValuesToThread(actionAndReason, speculation); 528 append(new AMD64DeoptimizeOp(state)); 529 } 530 531 @Override 532 public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { 533 Value actionAndReason = emitJavaConstant(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0)); 534 Value nullValue = emitConstant(LIRKind.reference(AMD64Kind.QWORD), JavaConstant.NULL_POINTER); 535 moveDeoptValuesToThread(actionAndReason, nullValue); 536 append(new AMD64HotSpotDeoptimizeCallerOp()); 537 } 538 539 @Override 540 public void beforeRegisterAllocation() { 541 super.beforeRegisterAllocation(); 542 boolean hasDebugInfo = getResult().getLIR().hasDebugInfo(); 543 AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo); 544 if (hasDebugInfo) { 545 getResult().setDeoptimizationRescueSlot(((AMD64FrameMapBuilder) getResult().getFrameMapBuilder()).allocateDeoptimizationRescueSlot()); 546 } 547 548 getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize()); 549 550 for (AMD64HotSpotRestoreRbpOp op : epilogueOps) { 551 op.setSavedRbp(savedRbp); 552 } 553 if (BenchmarkCounters.enabled) { 554 // ensure that the rescue slot is available 555 LIRInstruction op = getOrInitRescueSlotOp(); 556 // insert dummy instruction into the start block 557 LIR lir = getResult().getLIR(); 558 ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); 559 instructions.add(1, op); 560 Debug.dump(Debug.INFO_LOG_LEVEL, lir, "created rescue dummy op"); 561 } 562 } 563 564 @Override 565 public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { 566 LIRKind inputKind = pointer.getValueKind(LIRKind.class); 567 assert inputKind.getPlatformKind() == AMD64Kind.QWORD; 568 if (inputKind.isReference(0)) { 569 // oop 570 Variable result = newVariable(LIRKind.reference(AMD64Kind.DWORD)); 571 append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); 572 return result; 573 } else { 574 // metaspace pointer 575 Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); 576 AllocatableValue base = Value.ILLEGAL; 577 OptionValues options = getResult().getLIR().getOptions(); 578 if (encoding.hasBase() || GeneratePIC.getValue(options)) { 579 if (GeneratePIC.getValue(options)) { 580 Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); 581 AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); 582 append(move); 583 base = baseAddress; 584 } else { 585 base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); 586 } 587 } 588 append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); 589 return result; 590 } 591 } 592 593 @Override 594 public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) { 595 LIRKind inputKind = pointer.getValueKind(LIRKind.class); 596 assert inputKind.getPlatformKind() == AMD64Kind.DWORD; 597 if (inputKind.isReference(0)) { 598 // oop 599 Variable result = newVariable(LIRKind.reference(AMD64Kind.QWORD)); 600 append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); 601 return result; 602 } else { 603 // metaspace pointer 604 Variable result = newVariable(LIRKind.value(AMD64Kind.QWORD)); 605 AllocatableValue base = Value.ILLEGAL; 606 OptionValues options = getResult().getLIR().getOptions(); 607 if (encoding.hasBase() || GeneratePIC.getValue(options)) { 608 if (GeneratePIC.getValue(options)) { 609 Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); 610 AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); 611 append(move); 612 base = baseAddress; 613 } else { 614 base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); 615 } 616 } 617 append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); 618 return result; 619 } 620 } 621 622 @Override 623 public void emitNullCheck(Value address, LIRFrameState state) { 624 if (address.getValueKind().getPlatformKind() == AMD64Kind.DWORD) { 625 CompressEncoding encoding = config.getOopEncoding(); 626 Value uncompressed; 627 if (encoding.getShift() <= 3) { 628 LIRKind wordKind = LIRKind.unknownReference(target().arch.getWordKind()); 629 uncompressed = new AMD64AddressValue(wordKind, getProviders().getRegisters().getHeapBaseRegister().asValue(wordKind), asAllocatable(address), Scale.fromInt(1 << encoding.getShift()), 630 0); 631 } else { 632 uncompressed = emitUncompress(address, encoding, false); 633 } 634 append(new AMD64Move.NullCheckOp(asAddressValue(uncompressed), state)); 635 } else { 636 super.emitNullCheck(address, state); 637 } 638 } 639 640 @Override 641 public LIRInstruction createBenchmarkCounter(String name, String group, Value increment) { 642 if (BenchmarkCounters.enabled) { 643 return new AMD64HotSpotCounterOp(name, group, increment, getProviders().getRegisters(), config, getOrInitRescueSlot()); 644 } 645 throw GraalError.shouldNotReachHere("BenchmarkCounters are not enabled!"); 646 } 647 648 @Override 649 public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) { 650 if (BenchmarkCounters.enabled) { 651 return new AMD64HotSpotCounterOp(names, groups, increments, getProviders().getRegisters(), config, getOrInitRescueSlot()); 652 } 653 throw GraalError.shouldNotReachHere("BenchmarkCounters are not enabled!"); 654 } 655 656 @Override 657 public void emitPrefetchAllocate(Value address) { 658 append(new AMD64PrefetchOp(asAddressValue(address), config.allocatePrefetchInstr)); 659 } 660 661 @Override 662 protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) { 663 return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp); 664 } 665} 666