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