Objective
Because bastard oneself is to do the game development work, so usually also will add some player's group. And some of the problems that plague the players are also bothering us with these mobile game developers. This is not recently bastard to see some of their own group, often someone asked why this game update will be re-downloaded, and not in-game update it? As a game developer, or Unity3d program Ape, we all know that Unity3d does not support hot updates, and even generating new code on the iOS platform will cause the game error to crash (the word that bastard here emphasizes the generation of new code, is to remind you not to confuse Reflection.Emit and reflection). But do we, like ordinary players, see only the "can't" phenomenon, and not understand the reason behind the "can't"? The small bastard today, write their own ideas about the problem ~ ~ talk about who stole the player's hot update.
from a common error.
I do not know you crossing in the U3D program Ape in the development of iOS version of the time have encountered such an error:
ExecutionEngineException: Attempting to JIT compile method ' XXXX ' when running with--aot-only.
The meaning of this error is very clear, said is also very specific, the effect of translation into Chinese is in the use of--aot-only this option, and try to use the JIT compiler to compile the xxx method.
Then do not know whether there will be crossing think this problem may be the program running on the iOS platform, accidentally committed the taboo of iOS, using the JIT (assuming we do not know why the use of JIT is the taboo of iOS) to dynamically compile code caused by the error of iOS?
The answer is in the negative.
Or, further, seeing "executionengineexception" seems to have little to do with the exception of the iOS platform, which puts the onus on Unity3d's engine. It must be the game engine. JIT compilation is not supported at this time.
It's not all right, but it's close to the truth.
Think about it, who else could be involved in compiling a suspected object?
Well, it's not suspense. This exception is actually the exception of mono. In other words, Unity3d uses mono to compile, so the suspicion of Unity3d is ruled out. iOS does not make an error by generating or running dynamically generated code, in other words, the exception occurs before the iOS exception is triggered, so that the program crashes before it is JIT-compiled on the iOS platform.
When it comes to this, it's just a matter of how mono compiles the code. If we go to Mono's hosting page to see its source code, you can simply do a simple analysis of its directory structure, bastard briefly summarize the mono compiled part of the directory structure:
Docs |
For the Mono runtime documentation, here you can see examples of compiled documentation, as well as a list of the Mono runtime APIs that small bastard value |
Data |
Configuration files for some mono runtimes |
Mono |
The core of the Mono runtime is also the focus of this article on the Mono section, and briefly introduces several of its more important subdirectories |
|
|
Metadata |
Implements the logic to handle metadata |
|
|
Mini |
JIT Compiler (emphasis) |
|
|
Dis |
An anti-compiler that can execute CIL code |
|
|
Cil |
The XML configuration of the CIL instructions, where you can see what the CIL instructions are |
|
|
Arch |
Specific parts of different architectures. |
MCs |
C # source Compiler (C #---->cil) |
|
MCs |
|
|
|
|
MCs |
SOURCE Compiler |
|
|
Jay |
Generator of the parser program |
Well, specifically to let us talk about the JIT compilation, we need to see the Mini folder in the Mono directory, the files in this folder, the. c files have been JIT compiled.
The structure of this directory is truncated, because there are too many files:
But here little bastard want a flashback, that is, the first direct positioning of the error "executionengineexception:attempting to JIT compile method ' XXXX ' and running with-- Aot-only." Position, and then find out how it was triggered.
In this way, we come to the Mini.c file under Mono's JIT compiler directory Mini. This is the logical implementation of the JIT. And that part of the error? This is handled in the Mini.c file:
if ( ) { char *fullname = Mono_method_full_name (method, TRUE); char *msg = g_strdup_printf ( " Span style= "color: #800000;" >attempting to JIT compile method '%s ' while running with--aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.\n " *jit_ex = Mono_get_exception_execution_engine (msg); G_free (fullname); G_free (msg); return NULL;}
Mono_aot_only? Yes, as long as we set the compilation mode for mono to Full-aot (for example, when you hit the iOS installation package), when you try to use JIT compilation at run time, Mono's own JIT compiler prohibits this behavior and then reports the exception. JIT compilation process has not yet begun, it was killed by itself.
So what is JIT really a scourge? Why is iOS so taboo about it? Then you have to talk about the JIT.
Beautiful JIT because of what beautiful
The name is as its characteristic, jit--just in time, compiled on the fly.
What the? This is bastard, you're going to tell the guys? Isn't everyone aware of this? And a search on the internet is all jit=just in time. Okay, well, bastard's wrong. Then seriously define the JIT:
A program creates and runs new code as it runs, not the inherent code that was originally saved on the hard disk as part of the program. It's called JIT.
Several points:
- Program needs to run
- The generated code is the new code, not the ones that are present on the disk as part of the original program
- Not only generate code, but also run.
The 3rd need to be reminded is that the JIT is not just generating new code, it will also run the newly generated code. Then we'll start on this topic. But before bastard to explain, why is called JIT is beautiful.
As an example:
For example, one day you suddenly cross into a good scholar (well, this doesn't seem to have to go through), and now it's time to do a series of lectures in a country that doesn't speak. Faced with the dilemma of language, how to not make a fool of it?
Bastard has three options:
- Hire people to translate all the speeches at home. This is the easiest way to do this, but it lacks flexibility. For example, if there is a better topic or idea, you can only hate yourself for not learning a foreign language well.
- Hire a translator and start with you, he translates into what you say. There is no question of flexibility, because it is completely synchronous. But the disadvantage is equally obvious, translation to translate a lot of words, including what you say repeatedly. So it takes much more time than scenario 1.
- Hire a translator to set off with you, but not what you say he translated, but the record translated, encountered once translated will not be translated. You can communicate with others according to the previous translation record.
After reading these three projects, which of you crossing in mind more like?
Bastard's personal answer is scenario 3, because that's the way to JIT. So the beauty of the JIT is that it retains the flexibility to optimize the code and also the ability to reuse hot code.
Simulate the JIT process
JIT is so good, how does it implement both generating new code and running new code?
How the compiler generates code many articles are involved, bastard is not much here to ink. I'll talk to you about how to run the newly generated code.
First of all we need to know that the so-called machine code is the god horse thing. A line looks like a code that handles just a few numbers, and contains the machine code.
Char [] Maccode = {0x, 0x8b, 0x);
The Maccode corresponding assembly instructions are:
mov (%rdi),%rax
In fact, it can be seen that the machine code is bitstream, so it is not difficult to load it into memory. And the question is how it should be done.
All right. Let's simulate the process of executing the newly generated machine code. Assuming that the JIT has compiled a new machine code for us, it is a machine code for the SUM function:
Long (long num) {return1;} // the corresponding machine code
0x48, 0x, 0xc0, 0x,
First, we need to allocate space in memory before dynamically creating functions in memory. To simulate the dynamic creation of functions, in fact, is to map the corresponding machine code into memory space. Here we use the C language to do experiments, using the MMAP function to achieve this.
Header file |
#include <unistd.h> #include <sys/mman.h> |
Defining functions |
void *mmap (void *start, size_t length, int prot, int flags, int fd, off_t offsize) |
Function description |
Mmap () is used to map a file's contents into memory, and access to that area of memory is directly read and written to the contents of the file. |
Because we want to create the SUM function that is already a bit stream in memory and run it. So Mmap has several parameters to pay attention to.
Represents the protected mode of a mapped region, with the following combinations:
Prot_exec map area can be executed;
Prot_read map area can be read;
Prot_write mapping area can be written;
#include <stdio.h>
#include <stdlib.h>#include<string.h>#include<unistd.h>#include<sys/mman.h>//Allocating Memoryvoid*create_space (size_t size) {void* ptr = mmap (0, size, Prot_read| Prot_write |prot_exec, Map_private|Map_anon,-1,0); returnptr;}
So we get a piece of space assigned to us to store the code. The next step is to implement a method that copies the machine code, which is the bitstream, to the space allocated to us. You can use memcpy.
// Create a function in memory void Char* m) { char maccode[] = { 0x, 0x,0xc0 , 0x, c3 }; sizeof (Maccode));}
Then we're writing a main function to handle the entire logic:
#include <stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/mman.h>//Allocating Memoryvoid*create_space (size_t size) {void* ptr = mmap (0, size, Prot_read| Prot_write |prot_exec, Map_private|Map_anon,-1,0); returnptr;}//Create a function in memoryvoidCopy_code_2_space (unsignedChar*addr) {unsignedCharMaccode[] ={0x -, 0x the, 0xc0, 0x on, 0xc3}; memcpy (addr, Maccode,sizeof(Maccode));}//main declares a function pointer testfun used to point to the address of our SUM function in memoryintMainintargcChar**argv) { Constsize_t SIZE =1024x768; typedefLong(*testfun) (Long); void* Addr =Create_space (SIZE); Copy_code_2_space (addr); Testfun Test=addr; intresult = Test (1); printf ("result =%d\n", result); return 0;}
Compile and run to see the results:
// compiling gcc testfun.c // run ./a. Out1
The problem that left us
OK, so far, everything is going well. This example simulates the generation of dynamic code in memory and the subsequent run. There seems to be no problem? I wonder if you have overlooked a premise? That's the protection mode we've set for this area. But: readable, writable, executable! If there is no memory to read and write executable permissions, can our experiment succeed?
Let's get rid of the "executable"prot_exec permission in the create_space function and see what the result will look like.
Modify the code while the executable file that you just generated a.out deletes the rebuild run.
RM A.outvim testfun.cgcc testfun.c. /a. Out1
Results... The error!
Small conclusion
Therefore, iOS does not disable the JIT. Or, in other words, iOS blocks the executable permissions of memory (or heap), which is equivalent to blocking the JIT compilation in disguise. What's the reason? And listen to tell ~~~~~ who stole my hot update? Bets on iOS and security vulnerabilities
If you crossing think the article is well written, then the small bastard kneeling beg you to give a "recommendation", Thank you ~
Pretending to be
StatementOnce: This Bo article is not special note is original, if need to reprint please keep the original link (http://www.cnblogs.com/murongxiaopifu/p/4278947.html) and author information Murong Small Bastard
Who stole my hot update? Mono,jit,ios