@@ -852,7 +852,13 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
852
852
const bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0 ;
853
853
const bool makeInlineObservations = (compInlineResult != nullptr );
854
854
const bool isInlining = compIsForInlining ();
855
+ const bool isTier1 = opts.jitFlags ->IsSet (JitFlags::JIT_FLAG_TIER1);
856
+ const bool isPreJit = opts.jitFlags ->IsSet (JitFlags::JIT_FLAG_PREJIT);
857
+ const bool resolveTokens = makeInlineObservations && (isTier1 || isPreJit);
855
858
unsigned retBlocks = 0 ;
859
+ unsigned intrinsicCalls = 0 ;
860
+ int prefixFlags = 0 ;
861
+ int value = 0 ;
856
862
857
863
if (makeInlineObservations)
858
864
{
@@ -886,12 +892,14 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
886
892
compInlineResult->Note (InlineObservation::CALLEE_BEGIN_OPCODE_SCAN);
887
893
}
888
894
895
+ CORINFO_RESOLVED_TOKEN resolvedToken;
896
+ CORINFO_RESOLVED_TOKEN constrainedResolvedToken;
897
+ CORINFO_CALL_INFO callInfo;
898
+
889
899
while (codeAddr < codeEndp)
890
900
{
891
901
OPCODE opcode = (OPCODE)getU1LittleEndian (codeAddr);
892
902
codeAddr += sizeof (__int8);
893
- opts.instrCount ++;
894
- typeIsNormed = false ;
895
903
896
904
DECODE_OPCODE:
897
905
@@ -942,19 +950,72 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
942
950
// There has to be code after the call, otherwise the inlinee is unverifiable.
943
951
if (isInlining)
944
952
{
945
-
946
953
noway_assert (codeAddr < codeEndp - sz);
947
954
}
948
955
949
- // If the method has a call followed by a ret, assume that
950
- // it is a wrapper method.
951
- if (makeInlineObservations)
956
+ if (!makeInlineObservations)
952
957
{
953
- if ((OPCODE)getU1LittleEndian (codeAddr + sz) == CEE_RET)
958
+ break ;
959
+ }
960
+
961
+ CORINFO_METHOD_HANDLE methodHnd = nullptr ;
962
+ unsigned methodFlags = 0 ;
963
+ bool mustExpand = false ;
964
+ CorInfoIntrinsics intrinsicID = CORINFO_INTRINSIC_Illegal;
965
+ NamedIntrinsic ni = NI_Illegal;
966
+
967
+ if (resolveTokens)
968
+ {
969
+ impResolveToken (codeAddr, &resolvedToken, CORINFO_TOKENKIND_Method);
970
+ eeGetCallInfo (&resolvedToken,
971
+ (prefixFlags & PREFIX_CONSTRAINED) ? &constrainedResolvedToken : nullptr ,
972
+ combine (CORINFO_CALLINFO_KINDONLY,
973
+ (opcode == CEE_CALLVIRT) ? CORINFO_CALLINFO_CALLVIRT : CORINFO_CALLINFO_NONE),
974
+ &callInfo);
975
+
976
+ methodHnd = callInfo.hMethod ;
977
+ methodFlags = callInfo.methodFlags ;
978
+ }
979
+
980
+ if ((methodFlags & (CORINFO_FLG_INTRINSIC | CORINFO_FLG_JIT_INTRINSIC)) != 0 )
981
+ {
982
+ intrinsicCalls++;
983
+
984
+ if ((methodFlags & CORINFO_FLG_INTRINSIC) != 0 )
985
+ {
986
+ intrinsicID = info.compCompHnd ->getIntrinsicID (methodHnd, &mustExpand);
987
+ }
988
+
989
+ if ((methodFlags & CORINFO_FLG_JIT_INTRINSIC) != 0 )
954
990
{
955
- compInlineResult->Note (InlineObservation::CALLEE_LOOKS_LIKE_WRAPPER);
991
+ if (intrinsicID == CORINFO_INTRINSIC_Illegal)
992
+ {
993
+ ni = lookupNamedIntrinsic (methodHnd);
994
+
995
+ switch (ni)
996
+ {
997
+ case NI_IsSupported_True:
998
+ case NI_IsSupported_False:
999
+ {
1000
+ pushedStack.PushConstant ();
1001
+ break ;
1002
+ }
1003
+
1004
+ default :
1005
+ {
1006
+ break ;
1007
+ }
1008
+ }
1009
+ }
956
1010
}
957
1011
}
1012
+
1013
+ if ((OPCODE)getU1LittleEndian (codeAddr + sz) == CEE_RET)
1014
+ {
1015
+ // If the method has a call followed by a ret, assume that
1016
+ // it is a wrapper method.
1017
+ compInlineResult->Note (InlineObservation::CALLEE_LOOKS_LIKE_WRAPPER);
1018
+ }
958
1019
}
959
1020
break ;
960
1021
@@ -1085,17 +1146,79 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
1085
1146
break ;
1086
1147
1087
1148
case CEE_UNALIGNED:
1149
+ {
1150
+ noway_assert (sz == sizeof (__int8));
1151
+ prefixFlags |= PREFIX_UNALIGNED;
1152
+
1153
+ value = getU1LittleEndian (codeAddr);
1154
+ codeAddr += sizeof (__int8);
1155
+
1156
+ impValidateMemoryAccessOpcode (codeAddr, codeEndp, false );
1157
+ goto OBSERVE_OPCODE;
1158
+ }
1159
+
1088
1160
case CEE_CONSTRAINED:
1161
+ {
1162
+ noway_assert (sz == sizeof (unsigned ));
1163
+ prefixFlags |= PREFIX_CONSTRAINED;
1164
+
1165
+ if (resolveTokens)
1166
+ {
1167
+ impResolveToken (codeAddr, &constrainedResolvedToken, CORINFO_TOKENKIND_Constrained);
1168
+ }
1169
+ codeAddr += sizeof (unsigned );
1170
+
1171
+ {
1172
+ OPCODE actualOpcode = impGetNonPrefixOpcode (codeAddr, codeEndp);
1173
+
1174
+ if (actualOpcode != CEE_CALLVIRT)
1175
+ {
1176
+ BADCODE (" constrained. has to be followed by callvirt" );
1177
+ }
1178
+ }
1179
+ goto OBSERVE_OPCODE;
1180
+ }
1181
+
1089
1182
case CEE_READONLY:
1183
+ {
1184
+ noway_assert (sz == 0 );
1185
+ prefixFlags |= PREFIX_READONLY;
1186
+
1187
+ {
1188
+ OPCODE actualOpcode = impGetNonPrefixOpcode (codeAddr, codeEndp);
1189
+
1190
+ if ((actualOpcode != CEE_LDELEMA) && !impOpcodeIsCallOpcode (actualOpcode))
1191
+ {
1192
+ BADCODE (" readonly. has to be followed by ldelema or call" );
1193
+ }
1194
+ }
1195
+ goto OBSERVE_OPCODE;
1196
+ }
1197
+
1090
1198
case CEE_VOLATILE:
1199
+ {
1200
+ noway_assert (sz == 0 );
1201
+ prefixFlags |= PREFIX_VOLATILE;
1202
+
1203
+ impValidateMemoryAccessOpcode (codeAddr, codeEndp, true );
1204
+ goto OBSERVE_OPCODE;
1205
+ }
1206
+
1091
1207
case CEE_TAILCALL:
1092
1208
{
1093
- if (codeAddr >= codeEndp)
1209
+ noway_assert (sz == 0 );
1210
+ prefixFlags |= PREFIX_TAILCALL_EXPLICIT;
1211
+
1094
1212
{
1095
- goto TOO_FAR;
1213
+ OPCODE actualOpcode = impGetNonPrefixOpcode (codeAddr, codeEndp);
1214
+
1215
+ if (!impOpcodeIsCallOpcode (actualOpcode))
1216
+ {
1217
+ BADCODE (" tailcall. has to be followed by call, callvirt or calli" );
1218
+ }
1096
1219
}
1220
+ goto OBSERVE_OPCODE;
1097
1221
}
1098
- break ;
1099
1222
1100
1223
case CEE_STARG:
1101
1224
case CEE_STARG_S:
@@ -1312,6 +1435,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
1312
1435
// the list of other opcodes (for all platforms).
1313
1436
1314
1437
FALLTHROUGH;
1438
+
1315
1439
case CEE_MKREFANY:
1316
1440
case CEE_RETHROW:
1317
1441
if (makeInlineObservations)
@@ -1386,6 +1510,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
1386
1510
fgObserveInlineConstants (opcode, pushedStack, isInlining);
1387
1511
}
1388
1512
break ;
1513
+
1389
1514
case CEE_RET:
1390
1515
retBlocks++;
1391
1516
break ;
@@ -1397,13 +1522,23 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
1397
1522
// Skip any remaining operands this opcode may have
1398
1523
codeAddr += sz;
1399
1524
1525
+ // Clear any prefix flags that may have been set
1526
+ prefixFlags = 0 ;
1527
+
1528
+ // Increment the number of observed instructions
1529
+ opts.instrCount ++;
1530
+
1531
+ OBSERVE_OPCODE:
1532
+
1400
1533
// Note the opcode we just saw
1401
1534
if (makeInlineObservations)
1402
1535
{
1403
1536
InlineObservation obs =
1404
1537
typeIsNormed ? InlineObservation::CALLEE_OPCODE_NORMED : InlineObservation::CALLEE_OPCODE;
1405
1538
compInlineResult->NoteInt (obs, opcode);
1406
1539
}
1540
+
1541
+ typeIsNormed = false ;
1407
1542
}
1408
1543
1409
1544
if (codeAddr != codeEndp)
0 commit comments