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 */
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;
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 }
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;
|
1 /*
2 * Copyright (c) 2013, 2019, 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 */
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.EconomicSet;
52 import jdk.internal.vm.compiler.collections.Equivalence;
53 import org.graalvm.compiler.asm.Assembler;
54 import org.graalvm.compiler.asm.Label;
55 import org.graalvm.compiler.asm.sparc.SPARCAddress;
56 import org.graalvm.compiler.asm.sparc.SPARCAssembler;
57 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
58 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
59 import org.graalvm.compiler.code.CompilationResult;
60 import org.graalvm.compiler.code.DataSection;
61 import org.graalvm.compiler.code.DataSection.Data;
62 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
63 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
64 import org.graalvm.compiler.core.gen.LIRGenerationProvider;
65 import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules;
66 import org.graalvm.compiler.debug.CounterKey;
67 import org.graalvm.compiler.debug.DebugContext;
68 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
69 import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
70 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
71 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
72 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult;
73 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
74 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
75 import org.graalvm.compiler.hotspot.stubs.Stub;
76 import org.graalvm.compiler.lir.InstructionValueConsumer;
77 import org.graalvm.compiler.lir.LIR;
78 import org.graalvm.compiler.lir.LIRInstruction;
79 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
80 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
81 import org.graalvm.compiler.lir.asm.DataBuilder;
82 import org.graalvm.compiler.lir.asm.FrameContext;
83 import org.graalvm.compiler.lir.framemap.FrameMap;
84 import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
85 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
86 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
87 import org.graalvm.compiler.lir.sparc.SPARCCall;
88 import org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer;
89 import org.graalvm.compiler.lir.sparc.SPARCFrameMap;
90 import org.graalvm.compiler.lir.sparc.SPARCFrameMapBuilder;
91 import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin;
92 import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate;
93 import org.graalvm.compiler.lir.sparc.SPARCTailDelayedLIRInstruction;
94 import org.graalvm.compiler.nodes.StructuredGraph;
95 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
96 import org.graalvm.compiler.options.OptionValues;
97
98 import jdk.vm.ci.code.CallingConvention;
114 public SPARCHotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
115 super(config, runtime, providers);
116 }
117
118 private static class SizeEstimateStatistics {
119 private static final ConcurrentHashMap<String, CounterKey> counters = new ConcurrentHashMap<>();
120 private final String suffix;
121
122 SizeEstimateStatistics(String suffix) {
123 super();
124 this.suffix = suffix;
125 }
126
127 public void add(Class<?> c, int count, DebugContext debug) {
128 String name = SizeEstimateStatistics.class.getSimpleName() + "_" + c.getSimpleName() + "." + suffix;
129 CounterKey m = counters.computeIfAbsent(name, (n) -> DebugContext.counter(n));
130 m.add(debug, count);
131 }
132 }
133
134 @Override
135 protected FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
136 RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
137 FrameMap frameMap = new SPARCFrameMap(getCodeCache(), registerConfigNonNull, this);
138 return new SPARCFrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
139 }
140
141 @Override
142 public LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes) {
143 return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getVMConfig(), lirGenRes);
144 }
145
146 @Override
147 public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
148 return new SPARCHotSpotNodeLIRBuilder(graph, lirGen, new SPARCNodeMatchRules(lirGen));
149 }
150
151 @Override
152 protected void bangStackWithOffset(CompilationResultBuilder crb, int bangOffset) {
153 // Use SPARCAddress to get the final displacement including the stack bias.
154 SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
155 SPARCAddress address = new SPARCAddress(sp, -bangOffset);
156 if (SPARCAssembler.isSimm13(address.getDisplacement())) {
157 masm.stx(g0, address);
158 } else {
159 try (ScratchRegister sc = masm.getScratchRegister()) {
160 Register scratch = sc.getRegister();
161 assert isGlobalRegister(scratch) : "Only global (g1-g7) registers are allowed if the frame was not initialized here. Got register " + scratch;
162 masm.setx(address.getDisplacement(), scratch, false);
163 masm.stx(g0, new SPARCAddress(sp, scratch));
164 }
165 }
166 }
220 LIR lir = gen.getLIR();
221 assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
222
223 Stub stub = gen.getStub();
224 Assembler masm = new SPARCMacroAssembler(getTarget());
225 // On SPARC we always use stack frames.
226 HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
227 DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
228 OptionValues options = lir.getOptions();
229 DebugContext debug = lir.getDebug();
230 CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug,
231 compilationResult, Register.None);
232 crb.setTotalFrameSize(frameMap.totalFrameSize());
233 crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize());
234 StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
235 if (deoptimizationRescueSlot != null && stub == null) {
236 crb.compilationResult.setCustomStackAreaOffset(deoptimizationRescueSlot);
237 }
238
239 if (stub != null) {
240 updateStub(stub, gen, frameMap);
241 }
242 assert registerSizePredictionValidator(crb, debug);
243 return crb;
244 }
245
246 /**
247 * Registers a verifier which checks if the LIRInstructions estimate of constants size is
248 * greater or equal to the actual one.
249 */
250 private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb, DebugContext debug) {
251 /**
252 * Used to hold state between beforeOp and afterOp
253 */
254 class ValidationState {
255 LIRInstruction op;
256 final DebugContext debug;
257 int constantSizeBefore;
258
259 ValidationState(DebugContext debug) {
260 this.debug = debug;
|