Skip to content

Commit ea18e64

Browse files
committed
Experiment with signature
1 parent 1651e0f commit ea18e64

File tree

7 files changed

+132
-13
lines changed

7 files changed

+132
-13
lines changed

src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs

+29-1
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,25 @@ public void EmitJMP(ISymbolNode symbol)
9999
{
100100
Builder.EmitByte(0xE9);
101101
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32);
102-
103102
}
104103
}
105104

105+
public void EmitCALL(ISymbolNode symbol)
106+
{
107+
if (symbol.RepresentsIndirectionCell)
108+
{
109+
// CALL instruction with indirection
110+
Builder.EmitByte(0xFF);
111+
Builder.EmitByte(0x15);
112+
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32);
113+
}
114+
else
115+
{
116+
// Regular CALL instruction
117+
Builder.EmitByte(0xE8);
118+
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32);
119+
}
120+
}
106121
public void EmitJE(ISymbolNode symbol)
107122
{
108123
if (symbol.RepresentsIndirectionCell)
@@ -141,6 +156,14 @@ public void EmitJmpToAddrMode(ref AddrMode addrMode)
141156
EmitIndirInstruction(0xFF, 0x4, ref addrMode);
142157
}
143158

159+
public void EmitPUSH(Register reg)
160+
{
161+
if (reg >= Register.RAX && reg <= Register.R15)
162+
{
163+
Builder.EmitByte((byte)((byte)0x50 + (byte)((byte)reg & (byte)0x0F)));
164+
}
165+
}
166+
144167
public void EmitPUSH(sbyte imm8)
145168
{
146169
Builder.EmitByte(0x6A);
@@ -173,6 +196,11 @@ public void EmitPUSH(ISymbolNode node)
173196
}
174197
}
175198

199+
public void EmitPOP()
200+
{
201+
Builder.EmitByte(0x58);
202+
}
203+
176204
public void EmitRET()
177205
{
178206
Builder.EmitByte(0xC3);

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InterpreterStub.cs

+4-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
namespace ILCompiler.DependencyAnalysis.ReadyToRun
1515
{
1616
// An InterpreterStub is a small trampoline that
17-
// 1.) Push the InterpreterMethodInfo to the stack, and
18-
// 2.) Jump to the InterpreterMethod
17+
// 1.) Copy the pointer to the pointer to the InterpreterMethodInfo into RAX
18+
// 2.) Jump to the InterpreterRoutine
19+
//
1920
public class InterpreterStub : ObjectNode, ISymbolDefinitionNode
2021
{
2122
public InterpreterImport _interpreterImport;
@@ -34,10 +35,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
3435
{
3536
X64Emitter x64Emitter = new X64Emitter(factory, relocsOnly);
3637
x64Emitter.Builder.AddSymbol(this);
37-
x64Emitter.EmitMOV(Register.RCX, _interpreterImport);
38-
// TODO, andrewau, shouldn't have to do this if we can make node represent redirection cell
39-
AddrMode addr = new AddrMode(Register.RCX, null, 0, 0, AddrModeSize.Int64);
40-
x64Emitter.EmitMOV(Register.RCX, ref addr);
38+
x64Emitter.EmitMOV(Register.RAX, _interpreterImport);
4139
x64Emitter.EmitJMP(factory.InterpreterRoutineImport);
4240
return x64Emitter.Builder.ToObjectData();
4341
}

src/coreclr/vm/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ if(CLR_CMAKE_TARGET_ARCH_AMD64)
618618
${ARCH_SOURCES_DIR}/GenericComCallStubs.asm
619619
${ARCH_SOURCES_DIR}/GenericCLRToCOMCallStubs.asm
620620
${ARCH_SOURCES_DIR}/getstate.asm
621+
${ARCH_SOURCES_DIR}/interpreter.asm
621622
${ARCH_SOURCES_DIR}/JitHelpers_Fast.asm
622623
${ARCH_SOURCES_DIR}/JitHelpers_FastWriteBarriers.asm
623624
${ARCH_SOURCES_DIR}/JitHelpers_SingleAppDomain.asm
@@ -653,6 +654,7 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
653654
set(VM_SOURCES_WKS_ARCH_ASM
654655
${ARCH_SOURCES_DIR}/AsmHelpers.asm
655656
${ARCH_SOURCES_DIR}/CallDescrWorkerARM64.asm
657+
${ARCH_SOURCES_DIR}/interpreter.asm
656658
${ARCH_SOURCES_DIR}/patchedcode.asm
657659
${ARCH_SOURCES_DIR}/PInvokeStubs.asm
658660
${ARCH_SOURCES_DIR}/thunktemplates.asm

src/coreclr/vm/amd64/interpreter.asm

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; Licensed to the .NET Foundation under one or more agreements.
2+
; The .NET Foundation licenses this file to you under the MIT license.
3+
4+
; ***********************************************************************
5+
; File: JitHelpers_Fast.asm
6+
;
7+
; Notes: routinues which we believe to be on the hot path for managed
8+
; code in most scenarios.
9+
; ***********************************************************************
10+
11+
12+
include AsmMacros.inc
13+
include asmconstants.inc
14+
15+
extern ?InterpretMethod@@YA_JPEAUInterpreterMethodInfo@@PEAEPEAX@Z:proc
16+
17+
;
18+
; This routine rearrange the stack so that it will be the way coreclr!InterpretMethod wants.
19+
;
20+
; This routine should only be called by the InterpreterStub from ReadyToRun code, where it puts a pointer to a pointer to the InterpreterMethodInfo in rax and leave the argument untouched
21+
;
22+
; In the sequel, stack grows to the left (i.e. left hand side is lower virtual address), rsp always point to the leftmost (i.e. topmost) of the stack
23+
;
24+
; The state of right now
25+
;
26+
; rax -> &&InterpreterMethodInfo
27+
;
28+
; [ret] [s0] [s1] [s2] [s3] [spill args]
29+
;
30+
31+
;
32+
; Desired state before call
33+
;
34+
; rcx -> &InterpreterMethodInfo
35+
; rdx -> ilArgs = rsp + 20h
36+
; TODO: r8 should be stubContext, necessary for IL Stub
37+
;
38+
; +0h +8h +10h +18h +20h +28h +30h +38h
39+
; [s0] [s1] [s2] [s3] [rcx] [rdx] [r8] [r9] [na] [ret] [s0] [s1] [s2] [s3] [spill args]
40+
; <- shadow slots -> <- shadow slots ->
41+
;
42+
; The na slot is meant to make sure the stack is aligned
43+
;
44+
45+
NESTED_ENTRY InterpreterRoutine, _TEXT
46+
alloc_stack 48h
47+
48+
END_PROLOGUE
49+
mov [rsp+38h], r9
50+
mov [rsp+30h], r8
51+
mov [rsp+28h], rdx
52+
mov [rsp+20h], rcx
53+
mov rcx, [rax]
54+
lea rdx, [rsp + 20h]
55+
call ?InterpretMethod@@YA_JPEAUInterpreterMethodInfo@@PEAEPEAX@Z
56+
add rsp, 48h
57+
ret
58+
NESTED_END InterpreterRoutine, _TEXT
59+
60+
end

src/coreclr/vm/interpreter.h

+24-1
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,30 @@ class Interpreter
11251125
return *reinterpret_cast<BYTE**>(&m_ilArgs[m_methInfo->m_argDescs[argNum].m_nativeOffset]);
11261126
}
11271127
#endif
1128-
return &m_ilArgs[m_methInfo->m_argDescs[argNum].m_nativeOffset];
1128+
BYTE* argAddr = &m_ilArgs[m_methInfo->m_argDescs[argNum].m_nativeOffset];
1129+
if (argAddr >= m_ilArgs + 0x20)
1130+
{
1131+
//
1132+
// This is to adjust for the fact that the assembly stub does not know
1133+
// the signature of the method, and therefore it has no idea how many spill arg to copy
1134+
// so we are referencing the spill args where they were
1135+
//
1136+
// The stack look like this:
1137+
//
1138+
// top (low address) <- bottom (high address)
1139+
// [s0] [s1] [s2] [s3] [rcx] [rdx] [r8] [r9] [na] [ret] [s0] [s1] [s2] [s3] [spill args]
1140+
// ^
1141+
// m_ilArgs
1142+
// ^
1143+
// m_ilArgs + 0x20
1144+
// ^
1145+
// m_ilArgs + 0x30
1146+
//
1147+
// The end effect of the shift will make accessing [na] become accessing spill args, which is what we wanted
1148+
//
1149+
argAddr += 0x30;
1150+
}
1151+
return argAddr;
11291152
}
11301153
else
11311154
{

src/coreclr/vm/jitinterface.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@
5555
#include "interpreter.h"
5656
#endif // FEATURE_INTERPRETER
5757

58+
extern "C"
59+
{
60+
void InterpreterRoutine();
61+
}
62+
5863
#ifdef FEATURE_PERFMAP
5964
#include "perfmap.h"
6065
#endif
@@ -13790,7 +13795,7 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
1379013795
break;
1379113796

1379213797
case READYTORUN_HELPER_InterpreterRoutine:
13793-
result = (size_t)GetEEFuncEntryPoint(InterpretMethod);
13798+
result = (size_t)GetEEFuncEntryPoint(InterpreterRoutine);
1379413799
break;
1379513800

1379613801
case READYTORUN_HELPER_DelayLoad_Helper:

src/libraries/System.Private.CoreLib/src/System/AppContext.cs

+7-4
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,20 @@ internal static unsafe void Setup(char** pNames, char** pValues, int count)
165165
}
166166

167167
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
168-
private static void ReadyToCall()
168+
private static int ReadyToCall(int a, int b, int c, int d, int e, int f)
169169
{
170-
// Do nothing really
170+
return a * 1048576 + b * 65536 + c * 4096 + d * 256 + e * 16 + f;
171171
}
172172

173173
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
174174
private static Base Collatz()
175175
{
176176
#pragma warning disable IDE0054
177-
ReadyToCall(); // Should fail now?
178-
int a = 10086;
177+
int a = ReadyToCall(1, 2, 3, 4, 5, 6);
178+
if (a > 0)
179+
{
180+
throw new Exception(a.ToString());
181+
}
179182
while (a > 1)
180183
{
181184
if (a % 2 == 0)

0 commit comments

Comments
 (0)