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 package org.graalvm.compiler.hotspot.sparc; 24 25 import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; 26 import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; 27 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; 28 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; 29 import static jdk.vm.ci.sparc.SPARC.d32; 30 import static jdk.vm.ci.sparc.SPARC.d34; 31 import static jdk.vm.ci.sparc.SPARC.d36; 32 import static jdk.vm.ci.sparc.SPARC.d38; 33 import static jdk.vm.ci.sparc.SPARC.d40; 34 import static jdk.vm.ci.sparc.SPARC.d42; 35 import static jdk.vm.ci.sparc.SPARC.d44; 36 import static jdk.vm.ci.sparc.SPARC.d46; 37 import static jdk.vm.ci.sparc.SPARC.d48; 38 import static jdk.vm.ci.sparc.SPARC.d50; 39 import static jdk.vm.ci.sparc.SPARC.d52; 40 import static jdk.vm.ci.sparc.SPARC.d54; 41 import static jdk.vm.ci.sparc.SPARC.d56; 42 import static jdk.vm.ci.sparc.SPARC.d58; 43 import static jdk.vm.ci.sparc.SPARC.d60; 44 import static jdk.vm.ci.sparc.SPARC.d62; 45 import static jdk.vm.ci.sparc.SPARC.f0; 46 import static jdk.vm.ci.sparc.SPARC.f10; 47 import static jdk.vm.ci.sparc.SPARC.f12; 48 import static jdk.vm.ci.sparc.SPARC.f14; 49 import static jdk.vm.ci.sparc.SPARC.f16; 50 import static jdk.vm.ci.sparc.SPARC.f18; 51 import static jdk.vm.ci.sparc.SPARC.f2; 52 import static jdk.vm.ci.sparc.SPARC.f20; 53 import static jdk.vm.ci.sparc.SPARC.f22; 54 import static jdk.vm.ci.sparc.SPARC.f24; 55 import static jdk.vm.ci.sparc.SPARC.f26; 56 import static jdk.vm.ci.sparc.SPARC.f28; 57 import static jdk.vm.ci.sparc.SPARC.f30; 58 import static jdk.vm.ci.sparc.SPARC.f4; 59 import static jdk.vm.ci.sparc.SPARC.f6; 60 import static jdk.vm.ci.sparc.SPARC.f8; 61 import static jdk.vm.ci.sparc.SPARC.g1; 62 import static jdk.vm.ci.sparc.SPARC.g3; 63 import static jdk.vm.ci.sparc.SPARC.g4; 64 import static jdk.vm.ci.sparc.SPARC.g5; 65 import static jdk.vm.ci.sparc.SPARCKind.WORD; 66 import static jdk.vm.ci.sparc.SPARCKind.XWORD; 67 68 import java.util.Map; 69 70 import org.graalvm.compiler.core.common.LIRKind; 71 import org.graalvm.compiler.core.common.calc.Condition; 72 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 73 import org.graalvm.compiler.core.common.spi.LIRKindTool; 74 import org.graalvm.compiler.core.sparc.SPARCArithmeticLIRGenerator; 75 import org.graalvm.compiler.core.sparc.SPARCLIRGenerator; 76 import org.graalvm.compiler.debug.GraalError; 77 import org.graalvm.compiler.hotspot.CompressEncoding; 78 import org.graalvm.compiler.hotspot.HotSpotBackend; 79 import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; 80 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; 81 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; 82 import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; 83 import org.graalvm.compiler.hotspot.HotSpotLockStack; 84 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 85 import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; 86 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 87 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; 88 import org.graalvm.compiler.hotspot.stubs.Stub; 89 import org.graalvm.compiler.lir.LIRFrameState; 90 import org.graalvm.compiler.lir.LIRInstruction; 91 import org.graalvm.compiler.lir.LabelRef; 92 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; 93 import org.graalvm.compiler.lir.SwitchStrategy; 94 import org.graalvm.compiler.lir.Variable; 95 import org.graalvm.compiler.lir.VirtualStackSlot; 96 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 97 import org.graalvm.compiler.lir.sparc.SPARCAddressValue; 98 import org.graalvm.compiler.lir.sparc.SPARCControlFlow.StrategySwitchOp; 99 import org.graalvm.compiler.lir.sparc.SPARCFrameMapBuilder; 100 import org.graalvm.compiler.lir.sparc.SPARCImmediateAddressValue; 101 import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp; 102 import org.graalvm.compiler.lir.sparc.SPARCMove.NullCheckOp; 103 import org.graalvm.compiler.lir.sparc.SPARCMove.StoreOp; 104 import org.graalvm.compiler.lir.sparc.SPARCPrefetchOp; 105 import org.graalvm.compiler.lir.sparc.SPARCSaveRegistersOp; 106 107 import jdk.vm.ci.code.CallingConvention; 108 import jdk.vm.ci.code.Register; 109 import jdk.vm.ci.code.RegisterValue; 110 import jdk.vm.ci.code.StackSlot; 111 import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; 112 import jdk.vm.ci.hotspot.HotSpotObjectConstant; 113 import jdk.vm.ci.meta.AllocatableValue; 114 import jdk.vm.ci.meta.Constant; 115 import jdk.vm.ci.meta.DeoptimizationAction; 116 import jdk.vm.ci.meta.DeoptimizationReason; 117 import jdk.vm.ci.meta.JavaConstant; 118 import jdk.vm.ci.meta.JavaKind; 119 import jdk.vm.ci.meta.PlatformKind; 120 import jdk.vm.ci.meta.Value; 121 import jdk.vm.ci.meta.ValueKind; 122 import jdk.vm.ci.sparc.SPARC; 123 import jdk.vm.ci.sparc.SPARCKind; 124 125 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator { 126 127 final GraalHotSpotVMConfig config; 128 private HotSpotDebugInfoBuilder debugInfoBuilder; 129 private LIRFrameState currentRuntimeCallInfo; 130 131 public SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { 132 this(providers, config, lirGenRes, new ConstantTableBaseProvider()); 133 } 134 135 private SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, ConstantTableBaseProvider constantTableBaseProvider) { 136 this(new SPARCHotSpotLIRKindTool(), new SPARCArithmeticLIRGenerator(), new SPARCHotSpotMoveFactory(constantTableBaseProvider), providers, config, lirGenRes, constantTableBaseProvider); 137 } 138 139 public SPARCHotSpotLIRGenerator(LIRKindTool lirKindTool, SPARCArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, 140 LIRGenerationResult lirGenRes, ConstantTableBaseProvider constantTableBaseProvider) { 141 super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes, constantTableBaseProvider); 142 assert config.basicLockSize == 8; 143 this.config = config; 144 } 145 146 @Override 147 public HotSpotProviders getProviders() { 148 return (HotSpotProviders) super.getProviders(); 149 } 150 151 /** 152 * The slot reserved for storing the original return address when a frame is marked for 153 * deoptimization. The return address slot in the callee is overwritten with the address of a 154 * deoptimization stub. 155 */ 156 private StackSlot deoptimizationRescueSlot; 157 158 /** 159 * Value where the address for safepoint poll is kept. 160 */ 161 private AllocatableValue safepointAddressValue; 162 163 @Override 164 public VirtualStackSlot getLockSlot(int lockDepth) { 165 return getLockStack().makeLockSlot(lockDepth); 166 } 167 168 private HotSpotLockStack getLockStack() { 169 assert debugInfoBuilder != null && debugInfoBuilder.lockStack() != null; 170 return debugInfoBuilder.lockStack(); 171 } 172 173 @Override 174 public boolean needOnlyOopMaps() { 175 // Stubs only need oop maps 176 return getStub() != null; 177 } 178 179 public Stub getStub() { 180 return getResult().getStub(); 181 } 182 183 @Override 184 public HotSpotLIRGenerationResult getResult() { 185 return ((HotSpotLIRGenerationResult) super.getResult()); 186 } 187 188 @Override 189 public void beforeRegisterAllocation() { 190 super.beforeRegisterAllocation(); 191 boolean hasDebugInfo = getResult().getLIR().hasDebugInfo(); 192 if (hasDebugInfo) { 193 getResult().setDeoptimizationRescueSlot(((SPARCFrameMapBuilder) getResult().getFrameMapBuilder()).allocateDeoptimizationRescueSlot()); 194 } 195 196 getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize()); 197 } 198 199 @Override 200 protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { 201 currentRuntimeCallInfo = info; 202 super.emitForeignCallOp(linkage, result, arguments, temps, info); 203 } 204 205 @Override 206 public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { 207 HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; 208 Variable result; 209 LIRFrameState debugInfo = null; 210 if (hotspotLinkage.needsDebugInfo()) { 211 debugInfo = state; 212 assert debugInfo != null || getStub() != null; 213 } 214 215 if (linkage.destroysRegisters() || hotspotLinkage.needsJavaFrameAnchor()) { 216 HotSpotRegistersProvider registers = getProviders().getRegisters(); 217 Register thread = registers.getThreadRegister(); 218 Value threadTemp = newVariable(LIRKind.value(SPARCKind.XWORD)); 219 Register stackPointer = registers.getStackPointerRegister(); 220 Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); 221 append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer, threadTemp, spScratch)); 222 result = super.emitForeignCall(hotspotLinkage, debugInfo, args); 223 append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread, threadTemp)); 224 } else { 225 result = super.emitForeignCall(hotspotLinkage, debugInfo, args); 226 } 227 228 return result; 229 } 230 231 @Override 232 public void emitReturn(JavaKind javaKind, Value input) { 233 AllocatableValue operand = Value.ILLEGAL; 234 if (input != null) { 235 operand = resultOperandFor(javaKind, input.getValueKind()); 236 emitMove(operand, input); 237 } 238 append(new SPARCHotSpotReturnOp(operand, getStub() != null, config, getSafepointAddressValue())); 239 } 240 241 @Override 242 public void emitTailcall(Value[] args, Value address) { 243 throw GraalError.unimplemented(); 244 } 245 246 @Override 247 public void emitUnwind(Value exception) { 248 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER); 249 CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); 250 assert linkageCc.getArgumentCount() == 2; 251 RegisterValue exceptionParameter = (RegisterValue) linkageCc.getArgument(0); 252 emitMove(exceptionParameter, exception); 253 append(new SPARCHotSpotUnwindOp(exceptionParameter)); 254 } 255 256 private void moveDeoptValuesToThread(Value actionAndReason, Value speculation) { 257 moveValueToThread(actionAndReason, config.pendingDeoptimizationOffset); 258 moveValueToThread(speculation, config.pendingFailedSpeculationOffset); 259 } 260 261 private void moveValueToThread(Value v, int offset) { 262 LIRKind wordKind = LIRKind.value(target().arch.getWordKind()); 263 RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind); 264 SPARCAddressValue pendingDeoptAddress = new SPARCImmediateAddressValue(wordKind, thread, offset); 265 append(new StoreOp(v.getPlatformKind(), pendingDeoptAddress, load(v), null)); 266 } 267 268 @Override 269 public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { 270 moveDeoptValuesToThread(actionAndReason, speculation); 271 append(new SPARCDeoptimizeOp(state, target().arch.getWordKind())); 272 } 273 274 @Override 275 public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { 276 Value actionAndReason = emitJavaConstant(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0)); 277 Value nullValue = emitJavaConstant(JavaConstant.NULL_POINTER); 278 moveDeoptValuesToThread(actionAndReason, nullValue); 279 append(new SPARCHotSpotDeoptimizeCallerOp()); 280 } 281 282 @Override 283 public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { 284 ValueKind<?> kind = newValue.getValueKind(); 285 assert kind.equals(expectedValue.getValueKind()); 286 SPARCKind memKind = (SPARCKind) kind.getPlatformKind(); 287 Variable result = newVariable(newValue.getValueKind()); 288 append(new CompareAndSwapOp(result, asAllocatable(address), asAllocatable(expectedValue), asAllocatable(newValue))); 289 return emitConditionalMove(memKind, expectedValue, result, Condition.EQ, true, trueValue, falseValue); 290 } 291 292 @Override 293 public void emitPrefetchAllocate(Value address) { 294 SPARCAddressValue addr = asAddressValue(address); 295 append(new SPARCPrefetchOp(addr, config.allocatePrefetchInstr)); 296 } 297 298 public StackSlot getDeoptimizationRescueSlot() { 299 return deoptimizationRescueSlot; 300 } 301 302 @Override 303 public void emitCompareBranch(PlatformKind cmpKind, Value x, Value y, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, 304 double trueDestinationProbability) { 305 Value localX = x; 306 Value localY = y; 307 if (localX instanceof HotSpotObjectConstant) { 308 localX = load(localX); 309 } 310 if (localY instanceof HotSpotObjectConstant) { 311 localY = load(localY); 312 } 313 super.emitCompareBranch(cmpKind, localX, localY, cond, unorderedIsTrue, trueDestination, falseDestination, trueDestinationProbability); 314 } 315 316 @Override 317 protected boolean emitCompare(SPARCKind cmpKind, Value a, Value b) { 318 Value localA = a; 319 Value localB = b; 320 if (isConstantValue(a)) { 321 Constant c = asConstant(a); 322 if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { 323 localA = SPARC.g0.asValue(LIRKind.value(WORD)); 324 } else if (c instanceof HotSpotObjectConstant) { 325 localA = load(localA); 326 } 327 } 328 if (isConstantValue(b)) { 329 Constant c = asConstant(b); 330 if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { 331 localB = SPARC.g0.asValue(LIRKind.value(WORD)); 332 } else if (c instanceof HotSpotObjectConstant) { 333 localB = load(localB); 334 } 335 } 336 return super.emitCompare(cmpKind, localA, localB); 337 } 338 339 @Override 340 public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { 341 LIRKind inputKind = pointer.getValueKind(LIRKind.class); 342 assert inputKind.getPlatformKind() == XWORD : inputKind; 343 if (inputKind.isReference(0)) { 344 // oop 345 Variable result = newVariable(LIRKind.reference(WORD)); 346 append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); 347 return result; 348 } else { 349 // metaspace pointer 350 Variable result = newVariable(LIRKind.value(WORD)); 351 AllocatableValue base = Value.ILLEGAL; 352 if (encoding.base != 0) { 353 base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); 354 } 355 append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); 356 return result; 357 } 358 } 359 360 @Override 361 public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) { 362 LIRKind inputKind = pointer.getValueKind(LIRKind.class); 363 assert inputKind.getPlatformKind() == WORD; 364 if (inputKind.isReference(0)) { 365 // oop 366 Variable result = newVariable(LIRKind.reference(XWORD)); 367 append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); 368 return result; 369 } else { 370 // metaspace pointer 371 Variable result = newVariable(LIRKind.value(XWORD)); 372 AllocatableValue base = Value.ILLEGAL; 373 if (encoding.base != 0) { 374 base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); 375 } 376 append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); 377 return result; 378 } 379 } 380 381 /** 382 * @param savedRegisters the registers saved by this operation which may be subject to pruning 383 * @param savedRegisterLocations the slots to which the registers are saved 384 * @param supportsRemove determines if registers can be pruned 385 */ 386 protected SPARCSaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { 387 SPARCSaveRegistersOp save = new SPARCSaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); 388 append(save); 389 return save; 390 } 391 392 @Override 393 public SaveRegistersOp emitSaveAllRegisters() { 394 // We save all registers that were not saved by the save instruction. 395 // @formatter:off 396 Register[] savedRegisters = { 397 // CPU 398 g1, g3, g4, g5, 399 // FPU, use only every second register as doubles are stored anyways 400 f0, /*f1, */ f2, /*f3, */ f4, /*f5, */ f6, /*f7, */ 401 f8, /*f9, */ f10, /*f11,*/ f12, /*f13,*/ f14, /*f15,*/ 402 f16, /*f17,*/ f18, /*f19,*/ f20, /*f21,*/ f22, /*f23,*/ 403 f24, /*f25,*/ f26, /*f27,*/ f28, /*f29,*/ f30, /*f31 */ 404 d32, d34, d36, d38, 405 d40, d42, d44, d46, 406 d48, d50, d52, d54, 407 d56, d58, d60, d62 408 }; 409 // @formatter:on 410 AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; 411 for (int i = 0; i < savedRegisters.length; i++) { 412 PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); 413 VirtualStackSlot spillSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); 414 savedRegisterLocations[i] = spillSlot; 415 } 416 return emitSaveRegisters(savedRegisters, savedRegisterLocations, false); 417 } 418 419 @Override 420 public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { 421 append(new SPARCHotSpotLeaveCurrentStackFrameOp()); 422 } 423 424 @Override 425 public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { 426 append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp()); 427 } 428 429 @Override 430 public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { 431 Register thread = getProviders().getRegisters().getThreadRegister(); 432 Variable framePcVariable = load(framePc); 433 Variable senderSpVariable = load(senderSp); 434 Variable scratchVariable = newVariable(LIRKind.value(target().arch.getWordKind())); 435 append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable, 436 target().arch.getWordKind())); 437 } 438 439 @Override 440 public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { 441 Register thread = getProviders().getRegisters().getThreadRegister(); 442 append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset())); 443 } 444 445 @Override 446 public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { 447 Variable frameSizeVariable = load(frameSize); 448 Variable framePcVariable = load(framePc); 449 Variable senderSpVariable = load(senderSp); 450 Variable initialInfoVariable = load(initialInfo); 451 append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); 452 } 453 454 @Override 455 public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { 456 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); 457 458 Register threadRegister = getProviders().getRegisters().getThreadRegister(); 459 Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); 460 Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); 461 Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); 462 append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); 463 Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), trapRequest, mode); 464 append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); 465 466 Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = getResult().getCalleeSaveInfo(); 467 assert currentRuntimeCallInfo != null; 468 assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); 469 calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); 470 471 return result; 472 } 473 474 @Override 475 public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { 476 ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); 477 478 Register threadRegister = getProviders().getRegisters().getThreadRegister(); 479 Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); 480 Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); 481 Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); 482 append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); 483 Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), mode); 484 append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); 485 486 Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = getResult().getCalleeSaveInfo(); 487 assert currentRuntimeCallInfo != null; 488 assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); 489 calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); 490 491 return result; 492 } 493 494 @Override 495 public void emitNullCheck(Value address, LIRFrameState state) { 496 PlatformKind kind = address.getPlatformKind(); 497 if (kind == WORD) { 498 CompressEncoding encoding = config.getOopEncoding(); 499 Value uncompressed = emitUncompress(address, encoding, false); 500 append(new NullCheckOp(asAddressValue(uncompressed), state)); 501 } else { 502 super.emitNullCheck(address, state); 503 } 504 } 505 506 @Override 507 public LIRInstruction createBenchmarkCounter(String name, String group, Value increment) { 508 if (BenchmarkCounters.enabled) { 509 return new SPARCHotSpotCounterOp(name, group, increment, getProviders().getRegisters(), config); 510 } 511 throw GraalError.shouldNotReachHere("BenchmarkCounters are not enabled!"); 512 } 513 514 @Override 515 public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) { 516 if (BenchmarkCounters.enabled) { 517 return new SPARCHotSpotCounterOp(names, groups, increments, getProviders().getRegisters(), config); 518 } 519 throw GraalError.shouldNotReachHere("BenchmarkCounters are not enabled!"); 520 } 521 522 public AllocatableValue getSafepointAddressValue() { 523 if (this.safepointAddressValue == null) { 524 this.safepointAddressValue = newVariable(LIRKind.value(target().arch.getWordKind())); 525 } 526 return this.safepointAddressValue; 527 } 528 529 @Override 530 protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) { 531 return new SPARCHotSpotStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue); 532 } 533 534 public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) { 535 this.debugInfoBuilder = debugInfoBuilder; 536 } 537 538 @Override 539 public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) { 540 throw GraalError.unimplemented(); 541 } 542 543 @Override 544 public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) { 545 throw GraalError.unimplemented(); 546 } 547 }