use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class TraceGlobalMoveResolver method resolveMappings.
@SuppressWarnings("try")
private void resolveMappings() {
try (Indent indent = debug.logAndIndent("resolveMapping")) {
assert verifyBeforeResolve();
if (debug.isLogEnabled()) {
printMapping();
}
// This is necessary for detecting cycles in moves.
for (int i = mappingFrom.size() - 1; i >= 0; i--) {
Value from = mappingFrom.get(i);
block(from);
}
ArrayList<AllocatableValue> busySpillSlots = null;
while (mappingFrom.size() > 0) {
boolean processedInterval = false;
int spillCandidate = -1;
for (int i = mappingFrom.size() - 1; i >= 0; i--) {
Value fromLocation = mappingFrom.get(i);
AllocatableValue toLocation = mappingTo.get(i);
if (safeToProcessMove(fromLocation, toLocation)) {
// this interval can be processed because target is free
LIRInstruction move = insertMove(fromLocation, toLocation);
move.setComment(res, "TraceGlobalMoveResolver: resolveMapping");
unblock(fromLocation);
if (isStackSlotValue(toLocation)) {
if (busySpillSlots == null) {
busySpillSlots = new ArrayList<>(2);
}
busySpillSlots.add(toLocation);
}
mappingFrom.remove(i);
mappingFromStack.remove(i);
mappingTo.remove(i);
processedInterval = true;
} else if (fromLocation != null) {
if (isRegister(fromLocation) && (busySpillSlots == null || !busySpillSlots.contains(mappingFromStack.get(i)))) {
// this interval cannot be processed now because target is not free
// it starts in a register, so it is a possible candidate for spilling
spillCandidate = i;
} else if (isStackSlotValue(fromLocation) && spillCandidate == -1) {
// fall back to spill a stack slot in case no other candidate is found
spillCandidate = i;
}
}
}
if (!processedInterval) {
breakCycle(spillCandidate);
}
}
}
// check that all intervals have been processed
assert checkEmpty();
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class TraceRegisterAllocationPhase method run.
@Override
@SuppressWarnings("try")
protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
MoveFactory spillMoveFactory = context.spillMoveFactory;
RegisterAllocationConfig registerAllocationConfig = context.registerAllocationConfig;
LIR lir = lirGenRes.getLIR();
DebugContext debug = lir.getDebug();
TraceBuilderResult resultTraces = context.contextLookup(TraceBuilderResult.class);
GlobalLivenessInfo livenessInfo = context.contextLookup(GlobalLivenessInfo.class);
assert livenessInfo != null;
TraceAllocationContext traceContext = new TraceAllocationContext(spillMoveFactory, registerAllocationConfig, resultTraces, livenessInfo);
AllocatableValue[] cachedStackSlots = Options.TraceRACacheStackSlots.getValue(lir.getOptions()) ? new AllocatableValue[lir.numVariables()] : null;
// currently this is not supported
boolean neverSpillConstant = false;
final TraceRegisterAllocationPolicy plan = DefaultTraceRegisterAllocationPolicy.allocationPolicy(target, lirGenRes, spillMoveFactory, registerAllocationConfig, cachedStackSlots, resultTraces, neverSpillConstant, livenessInfo, lir.getOptions());
try (DebugContext.Scope s0 = debug.scope("AllocateTraces", resultTraces, livenessInfo)) {
for (Trace trace : resultTraces.getTraces()) {
tracesCounter.increment(debug);
TraceAllocationPhase<TraceAllocationContext> allocator = plan.selectStrategy(trace);
try (Indent i = debug.logAndIndent("Allocating Trace%d: %s (%s)", trace.getId(), trace, allocator);
DebugContext.Scope s = debug.scope("AllocateTrace", trace)) {
allocator.apply(target, lirGenRes, trace, traceContext);
}
}
} catch (Throwable e) {
throw debug.handle(e);
}
TraceGlobalMoveResolutionPhase.resolve(target, lirGenRes, traceContext);
deconstructSSAForm(lir);
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class BottomUpAllocator method allocateSpillSlot.
/**
* Returns a new spill slot or a cached entry if there is already one for the variable.
*/
private AllocatableValue allocateSpillSlot(Variable var) {
int variableIndex = var.index;
AllocatableValue cachedStackSlot = stackSlots[variableIndex];
if (cachedStackSlot != null) {
TraceRegisterAllocationPhase.globalStackSlots.increment(debug);
assert cachedStackSlot.getValueKind().equals(var.getValueKind()) : "CachedStackSlot: kind mismatch? " + var.getValueKind() + " vs. " + cachedStackSlot.getValueKind();
return cachedStackSlot;
}
VirtualStackSlot slot = lirGenRes.getFrameMapBuilder().allocateSpillSlot(var.getValueKind());
stackSlots[variableIndex] = slot;
TraceRegisterAllocationPhase.allocatedStackSlots.increment(debug);
return slot;
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class SubstrateAMD64RegisterConfig method getCallingConvention.
@Override
public CallingConvention getCallingConvention(Type t, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
SubstrateCallingConventionType type = (SubstrateCallingConventionType) t;
boolean isEntryPoint = type.nativeABI && !type.outgoing;
AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
int currentGeneral = 0;
int currentXMM = 0;
/*
* We have to reserve a slot between return address and outgoing parameters for the deopt
* frame handle. Exception: calls to native methods.
*/
int currentStackOffset = (type.nativeABI ? 0 : target.wordSize);
JavaKind[] kinds = new JavaKind[locations.length];
for (int i = 0; i < parameterTypes.length; i++) {
JavaKind kind = ObjectLayout.getCallSignatureKind(isEntryPoint, (ResolvedJavaType) parameterTypes[i], metaAccess, target);
kinds[i] = kind;
switch(kind) {
case Byte:
case Boolean:
case Short:
case Char:
case Int:
case Long:
case Object:
if (currentGeneral < generalParameterRegs.size()) {
Register register = generalParameterRegs.get(currentGeneral++);
locations[i] = register.asValue(valueKindFactory.getValueKind(kind.getStackKind()));
}
break;
case Float:
case Double:
if (currentXMM < xmmParameterRegs.size()) {
Register register = xmmParameterRegs.get(currentXMM++);
locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
}
break;
default:
throw shouldNotReachHere();
}
if (locations[i] == null) {
ValueKind<?> valueKind = valueKindFactory.getValueKind(kind.getStackKind());
locations[i] = StackSlot.get(valueKind, currentStackOffset, !type.outgoing);
currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize);
}
}
JavaKind returnKind = returnType == null ? JavaKind.Void : ObjectLayout.getCallSignatureKind(isEntryPoint, (ResolvedJavaType) returnType, metaAccess, target);
AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
return new SubstrateCallingConvention(type, kinds, currentStackOffset, returnLocation, locations);
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class LIRGenerator method emitForeignCall.
@Override
public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState frameState, Value... args) {
LIRFrameState state = null;
if (linkage.needsDebugInfo()) {
if (frameState != null) {
state = frameState;
} else {
assert needOnlyOopMaps();
state = new LIRFrameState(null, null, null);
}
}
// move the arguments into the correct location
CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
res.getFrameMapBuilder().callsMethod(linkageCc);
assert linkageCc.getArgumentCount() == args.length : "argument count mismatch";
Value[] argLocations = new Value[args.length];
for (int i = 0; i < args.length; i++) {
Value arg = args[i];
AllocatableValue loc = linkageCc.getArgument(i);
emitMove(loc, arg);
argLocations[i] = loc;
}
res.setForeignCall(true);
emitForeignCallOp(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state);
if (isLegal(linkageCc.getReturn())) {
return emitMove(linkageCc.getReturn());
} else {
return null;
}
}
Aggregations