1 /* 2 * Copyright (c) 2013, 2018, 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 */ 23 24 25 package org.graalvm.compiler.hotspot.sparc; 26 27 import static jdk.vm.ci.code.ValueUtil.asRegister; 28 import static jdk.vm.ci.code.ValueUtil.isRegister; 29 import static jdk.vm.ci.sparc.SPARC.g0; 30 import static jdk.vm.ci.sparc.SPARC.g5; 31 import static jdk.vm.ci.sparc.SPARC.i0; 32 import static jdk.vm.ci.sparc.SPARC.i7; 33 import static jdk.vm.ci.sparc.SPARC.l0; 34 import static jdk.vm.ci.sparc.SPARC.l7; 35 import static jdk.vm.ci.sparc.SPARC.o0; 36 import static jdk.vm.ci.sparc.SPARC.o7; 37 import static jdk.vm.ci.sparc.SPARC.sp; 38 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; 39 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister; 40 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; 41 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; 42 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc; 43 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; 44 import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; 45 46 import java.util.ArrayList; 47 import java.util.HashSet; 48 import java.util.Set; 49 import java.util.concurrent.ConcurrentHashMap; 50 51 import jdk.internal.vm.compiler.collections.EconomicMap; 52 import jdk.internal.vm.compiler.collections.EconomicSet; 53 import jdk.internal.vm.compiler.collections.Equivalence; 54 import org.graalvm.compiler.asm.Assembler; 55 import org.graalvm.compiler.asm.Label; 56 import org.graalvm.compiler.asm.sparc.SPARCAddress; 57 import org.graalvm.compiler.asm.sparc.SPARCAssembler; 58 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; 59 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister; 60 import org.graalvm.compiler.code.CompilationResult; 61 import org.graalvm.compiler.code.DataSection; 62 import org.graalvm.compiler.code.DataSection.Data; 63 import org.graalvm.compiler.core.common.CompilationIdentifier; 64 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; 65 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 66 import org.graalvm.compiler.core.gen.LIRGenerationProvider; 67 import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; 68 import org.graalvm.compiler.debug.CounterKey; 69 import org.graalvm.compiler.debug.DebugContext; 70 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 71 import org.graalvm.compiler.hotspot.HotSpotDataBuilder; 72 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 73 import org.graalvm.compiler.hotspot.HotSpotHostBackend; 74 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; 75 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; 76 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 77 import org.graalvm.compiler.hotspot.stubs.Stub; 78 import org.graalvm.compiler.lir.InstructionValueConsumer; 79 import org.graalvm.compiler.lir.LIR; 80 import org.graalvm.compiler.lir.LIRFrameState; 81 import org.graalvm.compiler.lir.LIRInstruction; 82 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; 83 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 84 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; 85 import org.graalvm.compiler.lir.asm.DataBuilder; 86 import org.graalvm.compiler.lir.asm.FrameContext; 87 import org.graalvm.compiler.lir.framemap.FrameMap; 88 import org.graalvm.compiler.lir.framemap.FrameMapBuilder; 89 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 90 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 91 import org.graalvm.compiler.lir.sparc.SPARCCall; 92 import org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer; 93 import org.graalvm.compiler.lir.sparc.SPARCFrameMap; 94 import org.graalvm.compiler.lir.sparc.SPARCFrameMapBuilder; 95 import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin; 96 import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate; 97 import org.graalvm.compiler.lir.sparc.SPARCTailDelayedLIRInstruction; 98 import org.graalvm.compiler.nodes.StructuredGraph; 99 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 100 import org.graalvm.compiler.options.OptionValues; 101 102 import jdk.vm.ci.code.CallingConvention; 103 import jdk.vm.ci.code.Register; 104 import jdk.vm.ci.code.RegisterConfig; 105 import jdk.vm.ci.code.StackSlot; 106 import jdk.vm.ci.hotspot.HotSpotCallingConventionType; 107 import jdk.vm.ci.meta.JavaType; 108 import jdk.vm.ci.meta.ResolvedJavaMethod; 109 110 /** 111 * HotSpot SPARC specific backend. 112 */ 113 public class SPARCHotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider { 114 115 private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE"); 116 private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL"); 117 118 public SPARCHotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { 119 super(config, runtime, providers); 120 } 121 122 private static class SizeEstimateStatistics { 123 private static final ConcurrentHashMap<String, CounterKey> counters = new ConcurrentHashMap<>(); 124 private final String suffix; 125 126 SizeEstimateStatistics(String suffix) { 127 super(); 128 this.suffix = suffix; 129 } 130 131 public void add(Class<?> c, int count, DebugContext debug) { 132 String name = SizeEstimateStatistics.class.getSimpleName() + "_" + c.getSimpleName() + "." + suffix; 133 CounterKey m = counters.computeIfAbsent(name, (n) -> DebugContext.counter(n)); 134 m.add(debug, count); 135 } 136 } 137 138 private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { 139 RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; 140 FrameMap frameMap = new SPARCFrameMap(getCodeCache(), registerConfigNonNull, this); 141 return new SPARCFrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull); 142 } 143 144 @Override 145 public LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes) { 146 return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getVMConfig(), lirGenRes); 147 } 148 149 @Override 150 public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) { 151 return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub, 152 config.requiresReservedStackCheck(graph.getMethods())); 153 } 154 155 @Override 156 public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { 157 return new SPARCHotSpotNodeLIRBuilder(graph, lirGen, new SPARCNodeMatchRules(lirGen)); 158 } 159 160 @Override 161 protected void bangStackWithOffset(CompilationResultBuilder crb, int bangOffset) { 162 // Use SPARCAddress to get the final displacement including the stack bias. 163 SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; 164 SPARCAddress address = new SPARCAddress(sp, -bangOffset); 165 if (SPARCAssembler.isSimm13(address.getDisplacement())) { 166 masm.stx(g0, address); 167 } else { 168 try (ScratchRegister sc = masm.getScratchRegister()) { 169 Register scratch = sc.getRegister(); 170 assert isGlobalRegister(scratch) : "Only global (g1-g7) registers are allowed if the frame was not initialized here. Got register " + scratch; 171 masm.setx(address.getDisplacement(), scratch, false); 172 masm.stx(g0, new SPARCAddress(sp, scratch)); 173 } 174 } 175 } 176 177 public class HotSpotFrameContext implements FrameContext { 178 179 final boolean isStub; 180 181 HotSpotFrameContext(boolean isStub) { 182 this.isStub = isStub; 183 } 184 185 @Override 186 public boolean hasFrame() { 187 return true; 188 } 189 190 @Override 191 public void enter(CompilationResultBuilder crb) { 192 final int frameSize = crb.frameMap.totalFrameSize(); 193 final int stackpointerChange = -frameSize; 194 SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; 195 if (!isStub) { 196 emitStackOverflowCheck(crb); 197 } 198 199 if (SPARCAssembler.isSimm13(stackpointerChange)) { 200 masm.save(sp, stackpointerChange, sp); 201 } else { 202 try (ScratchRegister sc = masm.getScratchRegister()) { 203 Register scratch = sc.getRegister(); 204 assert isGlobalRegister(scratch) : "Only global registers are allowed before save. Got register " + scratch; 205 masm.setx(stackpointerChange, scratch, false); 206 masm.save(sp, scratch, sp); 207 } 208 } 209 210 if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { 211 final int slotSize = 8; 212 for (int i = 0; i < frameSize / slotSize; ++i) { 213 // 0xC1C1C1C1 214 masm.stx(g0, new SPARCAddress(sp, i * slotSize)); 215 } 216 } 217 } 218 219 @Override 220 public void leave(CompilationResultBuilder crb) { 221 SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; 222 masm.restoreWindow(); 223 } 224 } 225 226 @Override 227 public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { 228 HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRes; 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 = new SPARCMacroAssembler(getTarget()); 234 // On SPARC we always use stack frames. 235 HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); 236 DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); 237 OptionValues options = lir.getOptions(); 238 DebugContext debug = lir.getDebug(); 239 CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, 240 compilationResult, Register.None); 241 crb.setTotalFrameSize(frameMap.totalFrameSize()); 242 crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); 243 StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); 244 if (deoptimizationRescueSlot != null && stub == null) { 245 crb.compilationResult.setCustomStackAreaOffset(deoptimizationRescueSlot); 246 } 247 248 if (stub != null) { 249 // Even on sparc we need to save floating point registers 250 EconomicSet<Register> destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); 251 EconomicMap<LIRFrameState, SaveRegistersOp> calleeSaveInfo = gen.getCalleeSaveInfo(); 252 updateStub(stub, destroyedCallerRegisters, calleeSaveInfo, frameMap); 253 } 254 assert registerSizePredictionValidator(crb, debug); 255 return crb; 256 } 257 258 /** 259 * Registers a verifier which checks if the LIRInstructions estimate of constants size is 260 * greater or equal to the actual one. 261 */ 262 private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb, DebugContext debug) { 263 /** 264 * Used to hold state between beforeOp and afterOp 265 */ 266 class ValidationState { 267 LIRInstruction op; 268 final DebugContext debug; 269 int constantSizeBefore; 270 271 ValidationState(DebugContext debug) { 272 this.debug = debug; 273 } 274 275 public void before(LIRInstruction before) { 276 assert op == null : "LIRInstruction " + op + " no after call received"; 277 op = before; 278 constantSizeBefore = calculateDataSectionSize(crb.compilationResult.getDataSection()); 279 } 280 281 public void after(LIRInstruction after) { 282 assert after.equals(op) : "Instructions before/after don't match " + op + "/" + after; 283 int constantSizeAfter = calculateDataSectionSize(crb.compilationResult.getDataSection()); 284 int actual = constantSizeAfter - constantSizeBefore; 285 if (op instanceof SPARCLIRInstructionMixin) { 286 org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate size = ((SPARCLIRInstructionMixin) op).estimateSize(); 287 assert size != null : "No size prediction available for op: " + op; 288 Class<?> c = op.getClass(); 289 CONSTANT_ESTIMATED_STATS.add(c, size.constantSize, debug); 290 CONSTANT_ACTUAL_STATS.add(c, actual, debug); 291 assert size.constantSize >= actual : "Op " + op + " exceeded estimated constant size; predicted: " + size.constantSize + " actual: " + actual; 292 } else { 293 assert actual == 0 : "Op " + op + " emitted to DataSection without any estimate."; 294 } 295 op = null; 296 constantSizeBefore = 0; 297 } 298 } 299 final ValidationState state = new ValidationState(debug); 300 crb.setOpCallback(op -> state.before(op), op -> state.after(op)); 301 return true; 302 } 303 304 private static int calculateDataSectionSize(DataSection ds) { 305 int sum = 0; 306 for (Data d : ds) { 307 sum += d.getSize(); 308 } 309 return sum; 310 } 311 312 @Override 313 public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { 314 SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; 315 // TODO: (sa) Fold the two traversals into one 316 stuffDelayedControlTransfers(lir); 317 int constantSize = calculateConstantSize(lir); 318 boolean canUseImmediateConstantLoad = constantSize < (1 << 13); 319 masm.setImmediateConstantLoad(canUseImmediateConstantLoad); 320 FrameMap frameMap = crb.frameMap; 321 RegisterConfig regConfig = frameMap.getRegisterConfig(); 322 Label unverifiedStub = installedCodeOwner == null || installedCodeOwner.isStatic() ? null : new Label(); 323 for (int i = 0; i < 2; i++) { 324 if (i > 0) { 325 crb.resetForEmittingCode(); 326 lir.resetLabels(); 327 resetDelayedControlTransfers(lir); 328 } 329 330 // Emit the prefix 331 if (unverifiedStub != null) { 332 crb.recordMark(config.MARKID_UNVERIFIED_ENTRY); 333 // We need to use JavaCall here because we haven't entered the frame yet. 334 CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCall, null, new JavaType[]{getProviders().getMetaAccess().lookupJavaType(Object.class)}, this); 335 Register inlineCacheKlass = g5; // see MacroAssembler::ic_call 336 337 try (ScratchRegister sc = masm.getScratchRegister()) { 338 Register scratch = sc.getRegister(); 339 Register receiver = asRegister(cc.getArgument(0)); 340 SPARCAddress src = new SPARCAddress(receiver, config.hubOffset); 341 342 masm.ldx(src, scratch); 343 masm.cmp(scratch, inlineCacheKlass); 344 } 345 BPCC.emit(masm, Xcc, NotEqual, NOT_ANNUL, PREDICT_NOT_TAKEN, unverifiedStub); 346 masm.nop(); // delay slot 347 } 348 349 masm.align(config.codeEntryAlignment); 350 crb.recordMark(config.MARKID_OSR_ENTRY); 351 crb.recordMark(config.MARKID_VERIFIED_ENTRY); 352 353 // Emit code for the LIR 354 crb.emit(lir); 355 } 356 profileInstructions(lir, crb); 357 358 HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; 359 HotSpotForeignCallsProvider foreignCalls = getProviders().getForeignCalls(); 360 if (!frameContext.isStub) { 361 crb.recordMark(config.MARKID_EXCEPTION_HANDLER_ENTRY); 362 SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, null); 363 crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); 364 SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER), null, null); 365 } else { 366 // No need to emit the stubs for entries back into the method since 367 // it has no calls that can cause such "return" entries 368 } 369 370 if (unverifiedStub != null) { 371 masm.bind(unverifiedStub); 372 try (ScratchRegister sc = masm.getScratchRegister()) { 373 Register scratch = sc.getRegister(); 374 SPARCCall.indirectJmp(crb, masm, scratch, foreignCalls.lookupForeignCall(IC_MISS_HANDLER)); 375 } 376 } 377 masm.peephole(); 378 } 379 380 private static int calculateConstantSize(LIR lir) { 381 int size = 0; 382 for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) { 383 if (block == null) { 384 continue; 385 } 386 for (LIRInstruction inst : lir.getLIRforBlock(block)) { 387 if (inst instanceof SPARCLIRInstructionMixin) { 388 SizeEstimate pred = ((SPARCLIRInstructionMixin) inst).estimateSize(); 389 if (pred != null) { 390 size += pred.constantSize; 391 } 392 } 393 } 394 } 395 return size; 396 } 397 398 private static void resetDelayedControlTransfers(LIR lir) { 399 for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) { 400 if (block == null) { 401 continue; 402 } 403 for (LIRInstruction inst : lir.getLIRforBlock(block)) { 404 if (inst instanceof SPARCDelayedControlTransfer) { 405 ((SPARCDelayedControlTransfer) inst).resetState(); 406 } 407 } 408 } 409 } 410 411 /** 412 * Fix-up over whole LIR. 413 * 414 * @see #stuffDelayedControlTransfers(LIR, AbstractBlockBase) 415 * @param l 416 */ 417 private static void stuffDelayedControlTransfers(LIR l) { 418 for (AbstractBlockBase<?> b : l.codeEmittingOrder()) { 419 if (b != null) { 420 stuffDelayedControlTransfers(l, b); 421 } 422 } 423 } 424 425 /** 426 * Tries to put DelayedControlTransfer instructions and DelayableLIRInstructions together. Also 427 * it tries to move the DelayedLIRInstruction to the DelayedControlTransfer instruction, if 428 * possible. 429 */ 430 private static void stuffDelayedControlTransfers(LIR l, AbstractBlockBase<?> block) { 431 ArrayList<LIRInstruction> instructions = l.getLIRforBlock(block); 432 if (instructions.size() >= 2) { 433 LIRDependencyAccumulator acc = new LIRDependencyAccumulator(); 434 SPARCDelayedControlTransfer delayedTransfer = null; 435 int delayTransferPosition = -1; 436 for (int i = instructions.size() - 1; i >= 0; i--) { 437 LIRInstruction inst = instructions.get(i); 438 boolean adjacent = delayTransferPosition - i == 1; 439 if (!adjacent || inst.destroysCallerSavedRegisters() || leavesRegisterWindow(inst)) { 440 delayedTransfer = null; 441 } 442 if (inst instanceof SPARCDelayedControlTransfer) { 443 delayedTransfer = (SPARCDelayedControlTransfer) inst; 444 acc.start(inst); 445 delayTransferPosition = i; 446 } else if (delayedTransfer != null) { 447 boolean overlap = acc.add(inst); 448 if (!overlap && inst instanceof SPARCTailDelayedLIRInstruction) { 449 // We have found a non overlapping LIR instruction which can be delayed 450 ((SPARCTailDelayedLIRInstruction) inst).setDelayedControlTransfer(delayedTransfer); 451 delayedTransfer = null; 452 } 453 } 454 } 455 } 456 } 457 458 private static boolean leavesRegisterWindow(LIRInstruction inst) { 459 return inst instanceof SPARCLIRInstructionMixin && ((SPARCLIRInstructionMixin) inst).leavesRegisterWindow(); 460 } 461 462 /** 463 * Accumulates inputs/outputs/temp/alive in a set along we walk back the LIRInstructions and 464 * detects, if there is any overlap. In this way LIRInstructions can be detected, which can be 465 * moved nearer to the DelayedControlTransfer instruction. 466 */ 467 private static class LIRDependencyAccumulator { 468 private final Set<Object> inputs = new HashSet<>(10); 469 private boolean overlap = false; 470 471 private final InstructionValueConsumer valueConsumer = (instruction, value, mode, flags) -> { 472 Object valueObject = value; 473 if (isRegister(value)) { // Canonicalize registers 474 valueObject = asRegister(value); 475 } 476 if (!inputs.add(valueObject)) { 477 overlap = true; 478 } 479 }; 480 481 public void start(LIRInstruction initial) { 482 inputs.clear(); 483 overlap = false; 484 initial.visitEachInput(valueConsumer); 485 initial.visitEachTemp(valueConsumer); 486 initial.visitEachAlive(valueConsumer); 487 } 488 489 /** 490 * Adds the inputs of lir instruction to the accumulator and returns, true if there was any 491 * overlap of parameters. 492 * 493 * @param inst 494 * @return true if an overlap was found 495 */ 496 public boolean add(LIRInstruction inst) { 497 overlap = false; 498 inst.visitEachOutput(valueConsumer); 499 inst.visitEachTemp(valueConsumer); 500 inst.visitEachInput(valueConsumer); 501 inst.visitEachAlive(valueConsumer); 502 return overlap; 503 } 504 } 505 506 @Override 507 public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { 508 RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; 509 return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); 510 } 511 512 @Override 513 public EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters) { 514 EconomicSet<Register> callerRegisters = EconomicSet.create(Equivalence.IDENTITY, calleeRegisters.size()); 515 for (Register register : calleeRegisters) { 516 if (l0.number <= register.number && register.number <= l7.number) { 517 // do nothing 518 } else if (o0.number <= register.number && register.number <= o7.number) { 519 // do nothing 520 } else if (i0.number <= register.number && register.number <= i7.number) { 521 // translate input to output registers 522 callerRegisters.add(translateInputToOutputRegister(register)); 523 } else { 524 callerRegisters.add(register); 525 } 526 } 527 return callerRegisters; 528 } 529 530 private Register translateInputToOutputRegister(Register register) { 531 assert i0.number <= register.number && register.number <= i7.number : "Not an input register " + register; 532 return getTarget().arch.getRegisters().get(o0.number + register.number - i0.number); 533 } 534 }