runtime: The "no." opcode prefix is not implemented

ECMA-335 specifies the no. opcode prefix as the following (III.2.2):

This prefix indicates that the subsequent instruction need not perform the specified fault check when it is executed. The byte that follows the instruction code indicates which checks can optionally be skipped.

In short, it allows for automatic type checks, range checks or null checks to be skipped, which would be useful for optimizing hot code paths.

The current implementation throws InvalidProgramException whenever it encounters this prefix. This opcode is simply marked as unused right now:

https://github.com/dotnet/coreclr/blob/8499136a9a79fd37a4acb9dc690a4815edd8081d/src/inc/opcode.def#L320

Here’s a simple method which reproduces the problem:

.method private hidebysig static 
	int32 NoPrefix () cil managed 
{
	.maxstack 2

	IL_0000: ldc.i4.1
	IL_0001: newarr [mscorlib]System.Int32
	IL_0006: ldc.i4.0
	IL_0007: no. 6 // this is rangecheck | nullcheck
	IL_000a: ldelem.i4
	IL_000b: ret
}

category:correctness theme:msil skill-level:intermediate cost:medium

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 10
  • Comments: 41 (39 by maintainers)

Commits related to this issue

Most upvoted comments

Implementing it so it is ignored …

Yes, a good first step would be to recognize and ignore the prefix. I would suggest being permissive in what you accept as any future extensions will likely have the “optional / hint” flavor to them too. So ignoring bits that are unspecified would be ok.

After that I would suggest working up a good set of test cases, and think through what should happen on them. Especially things like CSE candidates that differ only in no prefixes; we would want to make sure we handle the combinatorics properly (see for instance the recent work we have done for value numbering and exceptions: dotnet/coreclr#20129).

we can remove null checks based on C# 8.0 nonnull

Perhaps? It is not clear this is something the jit can rely on. And there are potentially other challenges: attribute recognition at jit time is expensive, and we may end up stripping this attribute away in implementation assemblies, at least in some cases.

Currently have set it to only read bits it should be concerned with, so yeah, invalid and zero values are allowed. Am currently attempting to implement removal of range checks through GTF_INX_RNGHCK, so that will give it some actual meaning.