How is the absolute back loop method embedded?

I mainly use C #, but I think this question might be suitable for other languages โ€‹โ€‹as well.
Also, there seems to be a lot of code here, but the question is very simple.

The attachment, as I understand it, is a compiler (in the case of C # - a virtual machine) that replaces a method call, inserting the method body in every place from which the method was called.

Let's say I have the following program:

static Main() { int number = 7; bool a; a = IsEven(number); Console.WriteLine(a); } 

... body of the IsEven method:

 bool IsEven(int n) { if (n % 2 == 0) // Two conditional return paths return true; else return false; } 

I understood how the code would look after embedding the method:

 static Main() { int number = 7; bool a; if (number % 2 == 0) a = true; else a = false; Console.WriteLine(a); // Will print true if 'number' is even, otherwise false } 

Obviously a simple and correct program.

But if I slightly correct the IsEven body to include the absolute return path ...

 bool IsEven(int n) { if (n % 2 == 0) return true; return false; // <- Absolute return path! } 

I personally like this style a little more in some situations. Some refraction tools may even suggest that I am modifying the first version to look like this, but when I tried to imagine what this method would look like when it was built in, I was at a dead end.
If we introduce the second version of the method:

 static Main() { int number = 7; bool a; if (number % 2 == 0) a = true; a = false; Console.WriteLine(a); // Will always print false! } 

Asked question:
How does the compiler / virtual machine deal with nesting a method that has an absolute return path?
It seems extremely unlikely that something like this will really prevent the use of the method, so I am wondering how this happens. Perhaps the attachment process is not as simple as this? Perhaps one version is likely to be built into the VM?

Edit: Profiling both methods (and manually inserting the first) showed no difference in performance, so I can only assume that both methods are embedded and work the same or similar (at least on my virtual machine).
In addition, these methods are extremely simple and seem almost interchangeable, but it can be much more difficult for complex methods with absolute return paths to change versions without absolute return paths.

+6
source share
3 answers

It can be difficult to explain what JITter does when it enters a line - it does not change C # code to do inlining - it will (always?) Work with the bytes created (compiled version) - and the "tools" you have when creating assembly code (actual bytes of machine code) are much smaller than yours in C # (or IL, for that matter).

This way you can have an idea of โ€‹โ€‹how this works in C # terms by considering the break keyword ..

Consider the possibility that each built-in function that is not trivial is enclosed in a while (true) or a do while(false) ), and that each source income is translated into a set of statements localVar = result; break; localVar = result; break; . Then you will get something like this:

 static Main() { int number = 7; bool a; while (true) { if (number % 2 == 0) { a = true; break; } a = false; break; } Console.WriteLine(a); // Will always print the right thing! Yey! } 

Similarly, when you create an assembly, you will see LOT of jmp generated - this is the moral equivalent of break statements, but they are MORE more flexible (think of them as anonymous gotos or something else).

So you can see that jitter (and any compiler that compiles to native) has many tools that it can use for the "right thing".

+6
source

The return indicates:

  • Result Value
  • Destruction of local variables (This applies to C ++, not to C #). In C #, finally and Dispose call blocks in using will be executed.
  • Jump out of function

All this happens after inlay. The jump will be local instead of cross-functions after insertion, but it will still be there.

An attachment is not textual substitution, such as C / C ++ macros.

Other things that differ between attachment and text replacement are handling variables with the same name.

+3
source

Machine code executed by the processor is a very simple language. It has no concept of a return statement; a routine has a single entry point and one exit point. So your IsEven () method looks like this:

 bool IsEven(int n) { if (n % 2 == 0) return true; return false; } 

need to rewrite jitter to something that resembles this (invalid C #):

 void IsEvent(int n) { if (n % 2 == 0) { $retval = true; goto exit; } $retval = false; exit: } // $retval becomes the function return value 

The $ retval variable may look fake here. It is not, it is an EAX register on the x86 core. Now you will see that this code is simple for inline, it can be transferred directly to the body of Main (). The $ retval variable can be equated to a with a simple logical substitution.

+2
source

Source: https://habr.com/ru/post/912159/


All Articles