1 /* |
1 /* |
2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * Copyright (c) 2018, Red Hat Inc. All rights reserved. |
3 * Copyright (c) 2018, Red Hat Inc. All rights reserved. |
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
5 * |
5 * |
6 * This code is free software; you can redistribute it and/or modify it |
6 * This code is free software; you can redistribute it and/or modify it |
7 * under the terms of the GNU General Public License version 2 only, as |
7 * under the terms of the GNU General Public License version 2 only, as |
36 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS; |
36 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS; |
37 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE; |
37 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE; |
38 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; |
38 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; |
39 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; |
39 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; |
40 |
40 |
|
41 import java.util.EnumSet; |
41 import java.util.function.Function; |
42 import java.util.function.Function; |
42 |
43 |
43 import org.graalvm.compiler.asm.Label; |
44 import org.graalvm.compiler.asm.Label; |
44 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; |
45 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; |
45 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; |
46 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; |
46 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; |
47 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; |
47 import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator; |
48 import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator; |
48 import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; |
49 import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; |
49 import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; |
50 import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; |
50 import org.graalvm.compiler.core.common.CompressEncoding; |
51 import org.graalvm.compiler.core.common.CompressEncoding; |
|
52 import org.graalvm.compiler.core.common.GraalOptions; |
51 import org.graalvm.compiler.core.common.LIRKind; |
53 import org.graalvm.compiler.core.common.LIRKind; |
52 import org.graalvm.compiler.core.common.calc.Condition; |
54 import org.graalvm.compiler.core.common.calc.Condition; |
53 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; |
55 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; |
54 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; |
56 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; |
55 import org.graalvm.compiler.core.common.spi.LIRKindTool; |
57 import org.graalvm.compiler.core.common.spi.LIRKindTool; |
66 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; |
68 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; |
67 import org.graalvm.compiler.hotspot.stubs.Stub; |
69 import org.graalvm.compiler.hotspot.stubs.Stub; |
68 import org.graalvm.compiler.lir.LIRFrameState; |
70 import org.graalvm.compiler.lir.LIRFrameState; |
69 import org.graalvm.compiler.lir.LIRInstruction; |
71 import org.graalvm.compiler.lir.LIRInstruction; |
70 import org.graalvm.compiler.lir.LabelRef; |
72 import org.graalvm.compiler.lir.LabelRef; |
71 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; |
73 import org.graalvm.compiler.lir.StandardOp.ZapRegistersOp; |
72 import org.graalvm.compiler.lir.SwitchStrategy; |
74 import org.graalvm.compiler.lir.SwitchStrategy; |
73 import org.graalvm.compiler.lir.Variable; |
75 import org.graalvm.compiler.lir.Variable; |
74 import org.graalvm.compiler.lir.VirtualStackSlot; |
76 import org.graalvm.compiler.lir.VirtualStackSlot; |
75 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; |
77 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; |
76 import org.graalvm.compiler.lir.aarch64.AArch64CCall; |
78 import org.graalvm.compiler.lir.aarch64.AArch64CCall; |
165 } |
167 } |
166 |
168 |
167 /** |
169 /** |
168 * @param savedRegisters the registers saved by this operation which may be subject to pruning |
170 * @param savedRegisters the registers saved by this operation which may be subject to pruning |
169 * @param savedRegisterLocations the slots to which the registers are saved |
171 * @param savedRegisterLocations the slots to which the registers are saved |
170 * @param supportsRemove determines if registers can be pruned |
|
171 */ |
172 */ |
172 protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { |
173 protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations) { |
173 AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); |
174 AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations); |
174 append(save); |
175 append(save); |
175 return save; |
176 return save; |
176 } |
177 } |
177 |
178 |
178 /** |
179 /** |
180 */ |
181 */ |
181 protected VirtualStackSlot allocateSaveRegisterLocation(Register register) { |
182 protected VirtualStackSlot allocateSaveRegisterLocation(Register register) { |
182 PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory()); |
183 PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory()); |
183 if (kind.getVectorLength() > 1) { |
184 if (kind.getVectorLength() > 1) { |
184 // we don't use vector registers, so there is no need to save them |
185 // we don't use vector registers, so there is no need to save them |
185 kind = AArch64Kind.QWORD; |
186 kind = AArch64Kind.DOUBLE; |
186 } |
187 } |
187 return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); |
188 return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); |
188 } |
189 } |
189 |
190 |
190 /** |
191 /** |
191 * Adds a node to the graph that saves all allocatable registers to the stack. |
192 * Adds a node to the graph that saves all allocatable registers to the stack. |
192 * |
193 * |
193 * @param supportsRemove determines if registers can be pruned |
|
194 * @return the register save node |
194 * @return the register save node |
195 */ |
195 */ |
196 private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) { |
196 private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters) { |
197 AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; |
197 AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; |
198 for (int i = 0; i < savedRegisters.length; i++) { |
198 for (int i = 0; i < savedRegisters.length; i++) { |
199 savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]); |
199 savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]); |
200 } |
200 } |
201 return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); |
201 return emitSaveRegisters(savedRegisters, savedRegisterLocations); |
202 } |
202 } |
203 |
203 |
204 protected void emitRestoreRegisters(AArch64SaveRegistersOp save) { |
204 protected void emitRestoreRegisters(AArch64SaveRegistersOp save) { |
205 append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save)); |
205 append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save)); |
206 } |
206 } |
345 HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; |
345 HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; |
346 boolean destroysRegisters = hotspotLinkage.destroysRegisters(); |
346 boolean destroysRegisters = hotspotLinkage.destroysRegisters(); |
347 |
347 |
348 AArch64SaveRegistersOp save = null; |
348 AArch64SaveRegistersOp save = null; |
349 Stub stub = getStub(); |
349 Stub stub = getStub(); |
350 if (destroysRegisters) { |
350 if (destroysRegisters && stub != null && stub.shouldSaveRegistersAroundCalls()) { |
351 if (stub != null && stub.preservesRegisters()) { |
351 Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray(); |
352 Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray(); |
352 save = emitSaveAllRegisters(savedRegisters); |
353 save = emitSaveAllRegisters(savedRegisters, true); |
|
354 } |
|
355 } |
353 } |
356 |
354 |
357 Variable result; |
355 Variable result; |
358 LIRFrameState debugInfo = null; |
356 LIRFrameState debugInfo = null; |
359 if (hotspotLinkage.needsDebugInfo()) { |
357 if (hotspotLinkage.needsDebugInfo()) { |
377 label = null; |
375 label = null; |
378 } else { |
376 } else { |
379 result = super.emitForeignCall(hotspotLinkage, debugInfo, args); |
377 result = super.emitForeignCall(hotspotLinkage, debugInfo, args); |
380 } |
378 } |
381 |
379 |
382 if (destroysRegisters) { |
380 if (save != null) { |
383 if (stub != null) { |
381 HotSpotLIRGenerationResult generationResult = getResult(); |
384 if (stub.preservesRegisters()) { |
382 LIRFrameState key = currentRuntimeCallInfo; |
385 HotSpotLIRGenerationResult generationResult = getResult(); |
383 if (key == null) { |
386 LIRFrameState key = currentRuntimeCallInfo; |
384 key = LIRFrameState.NO_STATE; |
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 } |
385 } |
|
386 assert !generationResult.getCalleeSaveInfo().containsKey(key); |
|
387 generationResult.getCalleeSaveInfo().put(key, save); |
|
388 emitRestoreRegisters(save); |
395 } |
389 } |
396 |
390 |
397 return result; |
391 return result; |
398 } |
392 } |
399 |
393 |
537 public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) { |
531 public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) { |
538 this.debugInfoBuilder = debugInfoBuilder; |
532 this.debugInfoBuilder = debugInfoBuilder; |
539 } |
533 } |
540 |
534 |
541 @Override |
535 @Override |
542 public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) { |
536 public ZapRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) { |
543 throw GraalError.unimplemented(); |
537 throw GraalError.unimplemented(); |
544 } |
538 } |
545 |
539 |
546 @Override |
540 @Override |
547 public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) { |
541 public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) { |
548 throw GraalError.unimplemented(); |
542 throw GraalError.unimplemented(); |
549 } |
543 } |
|
544 |
|
545 @Override |
|
546 public void emitZeroMemory(Value address, Value length, boolean isAligned) { |
|
547 int dczidValue = config.psrInfoDczidValue; |
|
548 EnumSet<AArch64.Flag> flags = ((AArch64) target().arch).getFlags(); |
|
549 |
|
550 // ARMv8-A architecture reference manual D12.2.35 Data Cache Zero ID register says: |
|
551 // * BS, bits [3:0] indicate log2 of the DC ZVA block size in (4-byte) words. |
|
552 // * DZP, bit [4] of indicates whether use of DC ZVA instruction is prohibited. |
|
553 int zvaLength = 4 << (dczidValue & 0xF); |
|
554 boolean isDcZvaProhibited = ((dczidValue & 0x10) != 0); |
|
555 |
|
556 // Use DC ZVA if it's not prohibited and AArch64 HotSpot flag UseBlockZeroing is on. |
|
557 boolean useDcZva = !isDcZvaProhibited && flags.contains(AArch64.Flag.UseBlockZeroing); |
|
558 |
|
559 // Set zva length negative (unknown at compile-time) for AOT compilation, since the value |
|
560 // could be different on different AArch64 CPU implementations. |
|
561 if (GraalOptions.ImmutableCode.getValue(getResult().getLIR().getOptions())) { |
|
562 useDcZva = false; |
|
563 } |
|
564 |
|
565 emitZeroMemory(address, length, isAligned, useDcZva, zvaLength); |
|
566 } |
550 } |
567 } |