|
|
@@ -1,44 +1,143 @@
|
|
|
Mono Ahead Of Time Compiler
|
|
|
===========================
|
|
|
|
|
|
-The new mono JIT has sophisticated optimization features. It uses SSA and has a
|
|
|
-pluggable architecture for further optimizations. This makes it possible and
|
|
|
-efficient to use the JIT also for AOT compilation.
|
|
|
+ The Ahead of Time compilation feature in Mono allows Mono to
|
|
|
+ precompile assemblies to minimize JIT time, reduce memory
|
|
|
+ usage at runtime and increase the code sharing across multiple
|
|
|
+ running Mono application.
|
|
|
|
|
|
+ To precompile an assembly use the following command:
|
|
|
+
|
|
|
+ mono --aot -O=all assembly.exe
|
|
|
|
|
|
-* file format: We use the native object format of the platform. That way it is
|
|
|
- possible to reuse existing tools like objdump and the dynamic loader. All we
|
|
|
- need is a working assembler, i.e. we write out a text file which is then
|
|
|
- passed to gas (the gnu assembler) to generate the object file.
|
|
|
+ The `--aot' flag instructs Mono to ahead-of-time compile your
|
|
|
+ assembly, while the -O=all flag instructs Mono to use all the
|
|
|
+ available optimizations.
|
|
|
|
|
|
-* file names: we simply add ".so" to the generated file. For example:
|
|
|
- basic.exe -> basic.exe.so
|
|
|
- corlib.dll -> corlib.dll.so
|
|
|
+* Position Independent Code
|
|
|
+---------------------------
|
|
|
|
|
|
-* staring the AOT compiler: mini --aot assembly_name
|
|
|
+ On x86 and x86-64 the code generated by Ahead-of-Time compiled
|
|
|
+ images is position-independent code. This allows the same
|
|
|
+ precompiled image to be reused across multiple applications
|
|
|
+ without having different copies: this is the same way in which
|
|
|
+ ELF shared libraries work: the code produced can be relocated
|
|
|
+ to any address.
|
|
|
|
|
|
-The following things are saved in the object file:
|
|
|
+ The implementation of Position Independent Code had a
|
|
|
+ performance impact on Ahead-of-Time compiled images but
|
|
|
+ compiler bootstraps are still faster than JIT-compiled images,
|
|
|
+ specially with all the new optimizations provided by the Mono
|
|
|
+ engine.
|
|
|
|
|
|
-* version infos:
|
|
|
+* How to support Position Independent Code in new Mono Ports
|
|
|
+------------------------------------------------------------
|
|
|
|
|
|
-* native code: this is labeled with method_XXXXXXXX: where XXXXXXXX is the
|
|
|
- hexadecimal token number of the method.
|
|
|
+ Generated native code needs to reference various runtime
|
|
|
+ structures/functions whose address is only known at run
|
|
|
+ time. JITted code can simple embed the address into the native
|
|
|
+ code, but AOT code needs to do an indirection. This
|
|
|
+ indirection is done through a table called the Global Offset
|
|
|
+ Table (GOT), which is similar to the GOT table in the Elf
|
|
|
+ spec. When the runtime saves the AOT image, it saves some
|
|
|
+ information for each method describing the GOT table entries
|
|
|
+ used by that method. When loading a method from an AOT image,
|
|
|
+ the runtime will fill out the GOT entries needed by the
|
|
|
+ method.
|
|
|
|
|
|
-* additional informations needed by the runtime: For example we need to store
|
|
|
- the code length and the exception tables. We also need a way to patch
|
|
|
- constants only available at runtime (for example vtable and class
|
|
|
- addresses). This is stored i a binary blob labeled method_info_XXXXXXXX:
|
|
|
+ * Computing the address of the GOT
|
|
|
|
|
|
-PROBLEMS:
|
|
|
+ Methods which need to access the GOT first need to compute its
|
|
|
+ address. On the x86 it is done by code like this:
|
|
|
|
|
|
-- all precompiled methods must be domain independent, or we add patch infos to
|
|
|
- patch the target doamin.
|
|
|
+ call <IP + 5>
|
|
|
+ pop ebx
|
|
|
+ add <OFFSET TO GOT>, ebx
|
|
|
+ <save got addr to a register>
|
|
|
|
|
|
-- the main problem is how to patch runtime related addresses, for example:
|
|
|
+ The variable representing the got is stored in
|
|
|
+ cfg->got_var. It is allways allocated to a global register to
|
|
|
+ prevent some problems with branches + basic blocks.
|
|
|
|
|
|
- - current application domain
|
|
|
- - string objects loaded with LDSTR
|
|
|
- - address of MonoClass data
|
|
|
- - static field offsets
|
|
|
- - method addreses
|
|
|
- - virtual function and interface slots
|
|
|
+ * Referencing GOT entries
|
|
|
+
|
|
|
+ Any time the native code needs to access some other runtime
|
|
|
+ structure/function (i.e. any time the backend calls
|
|
|
+ mono_add_patch_info ()), the code pointed by the patch needs
|
|
|
+ to load the value from the got. For example, instead of:
|
|
|
+
|
|
|
+ call <ABSOLUTE ADDR>
|
|
|
+ it needs to do:
|
|
|
+ call *<OFFSET>(<GOT REG>)
|
|
|
+
|
|
|
+ Here, the <OFFSET> can be 0, it will be fixed up by the AOT compiler.
|
|
|
+
|
|
|
+ For more examples on the changes required, see
|
|
|
+
|
|
|
+ svn diff -r 37739:38213 mini-x86.c
|
|
|
+
|
|
|
+* The Precompiled File Format
|
|
|
+-----------------------------
|
|
|
+
|
|
|
+ We use the native object format of the platform. That way it
|
|
|
+ is possible to reuse existing tools like objdump and the
|
|
|
+ dynamic loader. All we need is a working assembler, i.e. we
|
|
|
+ write out a text file which is then passed to gas (the gnu
|
|
|
+ assembler) to generate the object file.
|
|
|
+
|
|
|
+ The precompiled image is stored in a file next to the original
|
|
|
+ assembly that is precompiled with the native extension for a shared
|
|
|
+ library (on Linux its ".so" to the generated file).
|
|
|
+
|
|
|
+ For example: basic.exe -> basic.exe.so; corlib.dll -> corlib.dll.so
|
|
|
+
|
|
|
+ The following things are saved in the object file and can be
|
|
|
+ looked up using the equivalent to dlsym:
|
|
|
+
|
|
|
+ mono_assembly_guid
|
|
|
+
|
|
|
+ A copy of the assembly GUID.
|
|
|
+
|
|
|
+ mono_aot_version
|
|
|
+
|
|
|
+ The format of the AOT file format.
|
|
|
+
|
|
|
+ mono_aot_opt_flags
|
|
|
+
|
|
|
+ The optimizations flags used to build this
|
|
|
+ precompiled image.
|
|
|
+
|
|
|
+ method_infos
|
|
|
+
|
|
|
+
|
|
|
+ mono_icall_table
|
|
|
+
|
|
|
+ A table that lists all the internal calls
|
|
|
+ references by the precompiled image.
|
|
|
+
|
|
|
+ mono_image_table
|
|
|
+
|
|
|
+ A list of assemblies referenced by this AOT
|
|
|
+ module.
|
|
|
+
|
|
|
+ method_offsets
|
|
|
+
|
|
|
+ The equivalent to a procedure linkage table.
|
|
|
+
|
|
|
+ method_info_offsets
|
|
|
+
|
|
|
+* Considerations
|
|
|
+
|
|
|
+ [ This section is outdated ]
|
|
|
+
|
|
|
+[OUTDATED] All precompiled methods must be domain independent, or we add patch infos to
|
|
|
+[OUTDATED] patch the target doamin.
|
|
|
+[OUTDATED]
|
|
|
+[OUTDATED] The main problem is how to patch runtime related addresses, for example:
|
|
|
+[OUTDATED]
|
|
|
+[OUTDATED] - current application domain
|
|
|
+[OUTDATED] - string objects loaded with LDSTR
|
|
|
+[OUTDATED] - address of MonoClass data
|
|
|
+[OUTDATED] - static field offsets
|
|
|
+[OUTDATED] - method addreses
|
|
|
+[OUTDATED] - virtual function and interface slots
|