188188import jdk .vm .ci .code .CompilationRequest ;
189189import jdk .vm .ci .code .CompiledCode ;
190190import jdk .vm .ci .code .Register ;
191+ import jdk .vm .ci .code .RegisterAttributes ;
191192import jdk .vm .ci .code .RegisterConfig ;
192193import jdk .vm .ci .code .RegisterValue ;
193194import jdk .vm .ci .code .StackSlot ;
@@ -1097,6 +1098,41 @@ private static ForeignCallDescriptor chooseCPUFeatureVariant(ForeignCallDescript
10971098 }
10981099 }
10991100
1101+ /**
1102+ * Generates a method's prologue and epilogue.
1103+ * <p>
1104+ * Depending on the {@link SubstrateAMD64FrameMap frame map} properties and whether the rbp
1105+ * register is saved by the caller or the callee, we use different forms of prologue and
1106+ * epilogue.
1107+ *
1108+ * <pre>
1109+ *
1110+ * | preserveFramePointer |
1111+ * +----------------+----------------+
1112+ * | false | true |
1113+ * --------+----------------+----------------+
1114+ * | ; prologue | ; prologue |
1115+ * | sub rsp, #fs | push rbp |
1116+ * | | mov rbp, rsp |
1117+ * rbp is | | sub rsp, #fs |
1118+ * caller | | |
1119+ * saved | ; epilogue | ; epilogue |
1120+ * | add rsp, #fs | add rsp, #fs |
1121+ * | ret | pop rbp |
1122+ * | | ret |
1123+ * --------+----------------+----------------+
1124+ * | ; prologue | ; prologue |
1125+ * | push rbp | push rbp |
1126+ * | sub rsp, #fs | mov rbp, rsp |
1127+ * rbp is | | sub rsp, #fs |
1128+ * callee | | |
1129+ * saved | ; epilogue | ; epilogue |
1130+ * | add rsp, #fs | add rsp, #fs |
1131+ * | pop rbp | pop rbp |
1132+ * | ret | ret |
1133+ * --------+----------------+----------------+
1134+ * </pre>
1135+ */
11001136 protected static class SubstrateAMD64FrameContext implements FrameContext {
11011137
11021138 protected final SharedMethod method ;
@@ -1132,36 +1168,38 @@ protected final void reserveStackFrame(CompilationResultBuilder crb, AMD64MacroA
11321168 }
11331169
11341170 protected void maybePushBasePointer (CompilationResultBuilder crb , AMD64MacroAssembler asm ) {
1135- if (((SubstrateAMD64RegisterConfig ) crb .frameMap .getRegisterConfig ()).shouldUseBasePointer ()) {
1171+ SubstrateAMD64FrameMap frameMap = (SubstrateAMD64FrameMap ) crb .frameMap ;
1172+ if (frameMap .preserveFramePointer ()) {
11361173 /*
11371174 * Note that we never use the `enter` instruction so that we have a predictable code
11381175 * pattern at each method prologue. And `enter` seems to be slower than the explicit
11391176 * code.
11401177 */
11411178 asm .push (rbp );
11421179 asm .movq (rbp , rsp );
1180+ } else if (isCalleeSaved (rbp , frameMap .getRegisterConfig (), method )) {
1181+ asm .push (rbp );
11431182 }
11441183 }
11451184
11461185 @ Override
11471186 public void leave (CompilationResultBuilder crb ) {
11481187 AMD64MacroAssembler asm = (AMD64MacroAssembler ) crb .asm ;
1188+ SubstrateAMD64FrameMap frameMap = (SubstrateAMD64FrameMap ) crb .frameMap ;
11491189 crb .recordMark (SubstrateMarkId .EPILOGUE_START );
11501190
11511191 if (method .hasCalleeSavedRegisters ()) {
11521192 JavaKind returnKind = method .getSignature ().getReturnKind ();
11531193 Register returnRegister = null ;
11541194 if (returnKind != JavaKind .Void ) {
1155- returnRegister = crb . frameMap .getRegisterConfig ().getReturnRegister (returnKind );
1195+ returnRegister = frameMap .getRegisterConfig ().getReturnRegister (returnKind );
11561196 }
1157- AMD64CalleeSavedRegisters .singleton ().emitRestore (( AMD64MacroAssembler ) crb . asm , crb . frameMap .totalFrameSize (), returnRegister , crb );
1197+ AMD64CalleeSavedRegisters .singleton ().emitRestore (asm , frameMap .totalFrameSize (), returnRegister , crb );
11581198 }
11591199
1160- if ((( SubstrateAMD64RegisterConfig ) crb . frameMap .getRegisterConfig ()). shouldUseBasePointer ()) {
1161- asm . movq ( rsp , rbp );
1200+ asm . incrementq ( rsp , frameMap .frameSize ());
1201+ if ( frameMap . preserveFramePointer () || isCalleeSaved ( rbp , frameMap . getRegisterConfig (), method )) {
11621202 asm .pop (rbp );
1163- } else {
1164- asm .incrementq (rsp , crb .frameMap .frameSize ());
11651203 }
11661204
11671205 crb .recordMark (SubstrateMarkId .EPILOGUE_INCD_RSP );
@@ -1412,11 +1450,31 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
14121450 }
14131451 }
14141452
1415- private FrameMapBuilder newFrameMapBuilder (RegisterConfig registerConfig ) {
1416- RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache ().getRegisterConfig () : registerConfig ;
1417- FrameMap frameMap = new AMD64FrameMap (getProviders ().getCodeCache (), registerConfigNonNull , new SubstrateReferenceMapBuilderFactory (),
1418- ((SubstrateAMD64RegisterConfig ) registerConfigNonNull ).shouldUseBasePointer ());
1419- return new AMD64FrameMapBuilder (frameMap , getCodeCache (), registerConfigNonNull );
1453+ private FrameMapBuilder newFrameMapBuilder (RegisterConfig registerConfig , SharedMethod method ) {
1454+ FrameMap frameMap = new SubstrateAMD64FrameMap (getCodeCache (), (SubstrateAMD64RegisterConfig ) registerConfig , new SubstrateReferenceMapBuilderFactory (), method );
1455+ return new AMD64FrameMapBuilder (frameMap , getCodeCache (), registerConfig );
1456+ }
1457+
1458+ /**
1459+ * AMD64 Substrate VM specific frame map.
1460+ * <p>
1461+ * The layout is basically the same as {@link AMD64FrameMap} except that space for rbp is also
1462+ * reserved when rbp is callee saved, not just if {@link #preserveFramePointer} is true.
1463+ */
1464+ static class SubstrateAMD64FrameMap extends AMD64FrameMap {
1465+ SubstrateAMD64FrameMap (CodeCacheProvider codeCache , SubstrateAMD64RegisterConfig registerConfig , ReferenceMapBuilderFactory referenceMapFactory , SharedMethod method ) {
1466+ super (codeCache , registerConfig , referenceMapFactory , registerConfig .shouldUseBasePointer ());
1467+ if (!preserveFramePointer () && isCalleeSaved (rbp , registerConfig , method )) {
1468+ assert initialSpillSize == returnAddressSize () && spillSize == initialSpillSize : "rbp must be right after the return address" ;
1469+ initialSpillSize += getTarget ().wordSize ;
1470+ spillSize += getTarget ().wordSize ;
1471+ }
1472+ }
1473+ }
1474+
1475+ private static boolean isCalleeSaved (Register register , RegisterConfig config , SharedMethod method ) {
1476+ RegisterAttributes registerAttributes = config .getAttributesMap ()[register .number ];
1477+ return registerAttributes .isCalleeSave () || registerAttributes .isAllocatable () && method .hasCalleeSavedRegisters ();
14201478 }
14211479
14221480 @ Override
@@ -1425,7 +1483,7 @@ public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilat
14251483 SubstrateCallingConventionKind ccKind = method .getCallingConventionKind ();
14261484 SubstrateCallingConventionType ccType = ccKind .isCustom () ? method .getCustomCallingConventionType () : ccKind .toType (false );
14271485 CallingConvention callingConvention = CodeUtil .getCallingConvention (getCodeCache (), ccType , method , this );
1428- return new SubstrateLIRGenerationResult (compilationId , lir , newFrameMapBuilder (registerAllocationConfig .getRegisterConfig ()), callingConvention , registerAllocationConfig , method );
1486+ return new SubstrateLIRGenerationResult (compilationId , lir , newFrameMapBuilder (registerAllocationConfig .getRegisterConfig (), method ), callingConvention , registerAllocationConfig , method );
14291487 }
14301488
14311489 protected AMD64ArithmeticLIRGenerator createArithmeticLIRGen (RegisterValue nullRegisterValue ) {
0 commit comments