# HG changeset patch # User Andreas Woess # Date 1327832838 -3600 # Node ID b197bbb58d2fa05725cdb055e954c9ab90353c6d # Parent 5caca26cb1b9837823f484f38ed70c24145683e2 Fix and improve tail call. Fix flagsFor: Allow more than one input. Inputs and temporaries may only be registers. Remove redundant moves from emitCode, these are emitted by visitInvokeArguments in TailcallNode. Skip over empty slot for two-slot values in frame state. diff -r 5caca26cb1b9 -r b197bbb58d2f graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java Fri Jan 27 17:36:06 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java Sun Jan 29 11:27:18 2012 +0100 @@ -30,6 +30,7 @@ import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.hotspot.*; import com.oracle.max.graal.hotspot.target.amd64.*; +import com.oracle.max.graal.java.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.spi.*; import com.oracle.max.graal.nodes.type.*; @@ -62,10 +63,10 @@ CiKind[] signature = CiUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind(true)); CiCallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CiCallingConvention.Type.JavaCall, signature, gen.target(), false); - gen.frameMap().callsMethod(cc, CiCallingConvention.Type.JavaCall); + gen.frameMap().callsMethod(cc, CiCallingConvention.Type.JavaCall); // TODO (aw): I think this is unnecessary for a tail call. List parameters = new ArrayList<>(); - for (int i = 0; i < cc.locations.length; i++) { - parameters.add(frameState.localAt(i)); + for (int i = 0, slot = 0; i < cc.locations.length; i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) { + parameters.add(frameState.localAt(slot)); } List argList = gen.visitInvokeArguments(cc, parameters, null); diff -r 5caca26cb1b9 -r b197bbb58d2f graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java Fri Jan 27 17:36:06 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java Sun Jan 29 11:27:18 2012 +0100 @@ -37,9 +37,15 @@ * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance. */ public class AMD64TailcallOp extends AMD64LIRInstruction { + public AMD64TailcallOp(List parameters, CiValue target, CiValue[] callingConvention) { super("TAILCALL", LIRInstruction.NO_OPERANDS, null, toArray(parameters, target), LIRInstruction.NO_OPERANDS, callingConvention.clone()); assert inputs.length == temps.length + 1; + + for (int i = 0; i < temps.length; i++) { + assert isRegister(temps[i]) : "too many parameters for tail call"; + assert sameRegister(temps[i], inputs[i]) : "inputs do not match calling convention"; + } } private static CiValue[] toArray(List parameters, CiValue target) { @@ -51,19 +57,6 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // move all parameters to the correct positions, according to the calling convention - // TODO: These moves should not be part of the TAILCALL opcode, but emitted as separate MOVE instructions before. - for (int i = 0; i < inputs.length - 1; i++) { - assert inputs[i].kind == CiKind.Object || inputs[i].kind == CiKind.Int || inputs[i].kind == CiKind.Long : "only Object, int and long supported for now"; - assert isRegister(temps[i]) : "too many parameters"; - if (isRegister(inputs[i])) { - if (inputs[i] != temps[i]) { - masm.movq(asRegister(temps[i]), asRegister(inputs[i])); - } - } else { - masm.movq(asRegister(temps[i]), tasm.asAddress(inputs[i])); - } - } // destroy the current frame (now the return address is the top of stack) masm.leave(); @@ -74,10 +67,10 @@ @Override protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Stack); - } else if (mode == OperandMode.Temp && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + if (mode == OperandMode.Input) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Temp) { + return EnumSet.of(OperandFlag.Register); } throw Util.shouldNotReachHere(); }