diff options
author | Miguel de Icaza <miguel@gnome.org> | 2009-04-22 22:22:37 +0400 |
---|---|---|
committer | Miguel de Icaza <miguel@gnome.org> | 2009-04-22 22:22:37 +0400 |
commit | 1f781d02dc9d52b625e83691e2a05c20ba4167ec (patch) | |
tree | 2ebd6ccc34cc9961fe836cb55446b26a56974d9a /docs | |
parent | 87f46ffb330520d02a06b77efb1db0c447b6cf3d (diff) |
Move two other documents to the Wiki
svn path=/trunk/mono/; revision=132386
Diffstat (limited to 'docs')
-rw-r--r-- | docs/generic-sharing | 223 | ||||
-rw-r--r-- | docs/mini-porting.txt | 531 |
2 files changed, 0 insertions, 754 deletions
diff --git a/docs/generic-sharing b/docs/generic-sharing deleted file mode 100644 index a3bc994ba18..00000000000 --- a/docs/generic-sharing +++ /dev/null @@ -1,223 +0,0 @@ --*- outline -*- - -Generic code sharing -==================== - -* Porting - -** Generic class init trampoline - -The generic class init trampoline is very similar to the class init -trampoline, with the exception that the VTable of the class to be -inited is passed in a register, MONO_ARCH_VTABLE_REG. That register -can be the same as the IMT register. - -The call to the generic class init trampoline is never patched because -the VTable is not constant - it depends on the type arguments of the -class/method doing the call to the trampoline. For that reason, the -trampoline needs a fast path for the case that the class is already -inited, i.e. the trampoline needs to check the initialized bit of the -MonoVTable and immediately return if it is set. See tramp-x86.c for -how to portably figure out the number of the bit in the bit-field that -needs to be checked. - -Since the MONO_ARCH_VTABLE_REG is needed by the generic class init -trampoline function (in mini-trampolines.c) it needs to be saved by -the generic trampoline code in the register save block which is passed -to the trampoline. This also applies to the RGCTX fetch trampoline -(see below). - -Like the normal class init trampoline, the result of the generic class -init trampoline function is not a pointer to code that needs to be -jumped to. Instead, just like for the class init trampoline, the -generic trampoline code must return to the caller instead of jumping -to the returned value. The same applies for the RGCTX fetch -trampoline (see below). - -** RGCTX register - -Generic shared code needs access to type information. This -information is contained in a RGCTX for non-generic methods and in an -MRGCTX for generic methods. It is passed in one of several ways, -depending on the type of the called method: - - 1. Non-generic non-static methods of reference types have access to - the RGCTX via the "this" argument (this->vtable->rgctx). - - 2. Non-generic static methods of reference types and non-generic - methods of value types need to be passed a pointer to the - caller's class's VTable in the MONO_ARCH_RGCTX_REG register. - - 3. Generic methods need to be passed a pointer to the MRGCTX in the - MONO_ARCH_RGCTX_REG register. - -The MONO_ARCH_RGCTX_REG must not be clobbered by trampolines. - -MONO_ARCH_RGCTX_REG can be the same as the IMT register for now, but -this might change in the future when we implement virtual generic -method calls (more) efficiently. - -This register lifetime starts at the call site that loads it and -ends in the callee prologue when it is either discarded or stored -into a local variable. - -It's better to avoid registers used for argument passing for the RGCTX -as it would make the code dealing with calling conventions code a lot -harder. - -** Method prologue - -Generic shared code that have a RGCTX receive it in RGCTX_REG. There -must be a check in mono_arch_emit_prolog for MonoCompile::rgctx_var -and if set store it. See mini-x86.c for reference. - -** Dealing with types - -Types passed to arch functions might be type parameters -(MONO_TYPE_(M)VAR) if the MonoGenericSharingContext* argument is -non-NULL. For example, an argument or return type in a method passed -to mono_arch_find_this_argument() could be a MONO_TYPE_VAR. To guard -for that case use mini_get_basic_type_from_generic() on the type. See -get_call_info() in mini-x86.c, for example. - -** (M)RGCTX lazy fetch trampoline - -The purpose of the lazy fetch trampoline is to fetch a slot from an -(M)RGCTX which might not be inited, yet. In the latter case, it needs -to go make a transition to unmanaged code to fill the slot. This is -the layout of a RGCTX: - - +---------------------------------+ - | next | slot 0 | slot 1 | slot 2 | - +--|------------------------------+ - | - +-----+ - | +--------------------------------- - +->| next | slot 3 | slot 4 | slot 5 .... - +--|------------------------------ - | - +-----+ - | +------------------------------------ - +->| next | slot 10 | slot 11 | slot 12 .... - +--|--------------------------------- - . - . - . - -For fetching a slot from a RGCTX the trampoline is passed a pointer -(as a normal integer argument) to the VTable. From there it has to -fetch the pointer to the RGCTX, which might be null. Then it has to -traverse the correct number of "next" links, each of which might be -NULL. Arriving at the right array it needs to fetch the slot, which -might also be NULL. If any of the NULL cases, the trampoline must -transition to unmanaged code to potentially setup the RGCTX and fill -the slot. Here is pseudo-code for fetching slot 11: - - ; vtable ptr in r1 - ; fetch RGCTX array 0 - r2 = *(r1 + offsetof(MonoVTable, runtime_generic_context)) - if r2 == NULL goto unmanaged - ; fetch RGCTX array 1 - r2 = *r2 - if r2 == NULL goto unmanaged - ; fetch RGCTX array 2 - r2 = *r2 - if r2 == NULL goto unmanaged - ; fetch slot 11 - r2 = *(r2 + 2 * sizeof (gpointer)) - if r2 == NULL goto unmanaged - return r2 - unmanaged: - jump unmanaged_fetch_code - -The number of slots in the arrays must be obtained from the function -mono_class_rgctx_get_array_size(). - -The MRGCTX case is different in two aspects. First, the trampoline is -not passed a pointer to a VTable, but a pointer directly to the -MRGCTX, which is guaranteed not to be NULL (any of the next pointers -and any of the slots can be NULL, though). Second, the layout of the -first array is slightly different, in that the first two slots are -occupied by a pointers to the class's VTable and to the method's -method_inst. The next pointer is in the third slot and the first -actual slot, "slot 0", in the fourth: - - +--------------------------------------------------------+ - | vtable | method_inst | next | slot 0 | slot 1 | slot 2 | - +-------------------------|------------------------------+ - . - . - -All other arrays have the same layout as the RGCTX ones, except -possibly for their length. - -The function to create the trampoline, -mono_arch_create_rgctx_lazy_fetch_trampoline(), gets passed an encoded -slot number. Use the macro MONO_RGCTX_SLOT_IS_MRGCTX to query whether -a trampoline for an MRGCTX is needed, as opposed to one for a RGCTX. -Use MONO_RGCTX_SLOT_INDEX to get the index of the slot (like 2 for -"slot 2" as above). - -The unmanaged fetch code is yet another trampoline created via -mono_arch_create_specific_trampoline(), of type -MONO_TRAMPOLINE_RGCTX_LAZY_FETCH. It's given the slot number as the -trampoline argument. In addition, the pointer to the VTable/MRGCTX is -passed in MONO_ARCH_VTABLE_REG (like the VTable to the generic class -init trampoline - see above). - -Like the class init and generic class init trampolines, the RGCTX -fetch trampoline code doesn't return code that must be jumped to, so, -like for those trampolines (see above), the generic trampoline code -must do a normal return instead. - - -* Getting generics information about a stack frame - -If a method is compiled with generic sharing, its MonoJitInfo has -has_generic_jit_info set. In that case, the MonoJitInfo is followed -(after the MonoJitExceptionInfo array) by a MonoGenericJitInfo. - -The MonoGenericJitInfo contains information about the location of the -this/vtable/MRGCTX variable, if the has_this flag is set. If that is -the case, there are two possibilities: - - 1. this_in_reg is set. this_reg is the number of the register where - the variable is stored. - - 2. this_in_reg is not set. The variable is stored at offset - this_offset from the address in the register with number - this_reg. - -The variable can either point to the "this" object, to a vtable or to -an MRGCTX: - - 1. If the method is a non-generic non-static method of a reference - type, the variable points to the "this" object. - - 2. If the method is a non-generic static method or a non-generic - method of a value type, the variable points to the vtable of the - class. - - 3. If the method is a generic method, the variable points to the - MRGCTX of the method. - - -* Layout of the MRGCTX - -The MRGCTX is a structure that starts with -MonoMethodRuntimeGenericContext, which contains a pointer to the -vtable of the class and a pointer to the MonoGenericInst with the type -arguments for the method. - - -* Blog posts about generic code sharing - -http://schani.wordpress.com/2007/09/22/generics-sharing-in-mono/ -http://schani.wordpress.com/2007/10/12/the-trouble-with-shared-generics/ -http://schani.wordpress.com/2007/10/15/a-quick-generics-sharing-update/ -http://schani.wordpress.com/2008/01/29/other-types/ -http://schani.wordpress.com/2008/02/25/generic-types-are-lazy/ -http://schani.wordpress.com/2008/03/10/sharing-static-methods/ -http://schani.wordpress.com/2008/04/22/sharing-everything-and-saving-memory/ -http://schani.wordpress.com/2008/06/02/sharing-generic-methods/ -http://schani.wordpress.com/2008/06/27/another-generic-sharing-update/ diff --git a/docs/mini-porting.txt b/docs/mini-porting.txt deleted file mode 100644 index e629aff8df7..00000000000 --- a/docs/mini-porting.txt +++ /dev/null @@ -1,531 +0,0 @@ - Mono JIT porting guide. - Paolo Molaro (lupus@ximian.com) - -* Introduction - - This documents describes the process of porting the mono JIT - to a new CPU architecture. The new mono JIT has been designed - to make porting easier though at the same time enable the port - to take full advantage from the new architecture features and - instructions. Knowledge of the mini architecture (described in - the mini-doc.txt file) is a requirement for understanding this - guide, as well as an earlier document about porting the mono - interpreter (available on the web site). - - There are six main areas that a port needs to implement to - have a fully-functional JIT for a given architecture: - - 1) instruction selection - 2) native code emission - 3) call conventions and register allocation - 4) method trampolines - 5) exception handling - 6) minor helper methods - - To take advantage of some not-so-common processor features - (for example conditional execution of instructions as may be - found on ARM or ia64), it may be needed to develop an - high-level optimization, but doing so is not a requirement for - getting the JIT to work. - - We'll see in more details each of the steps required, note, - though, that a new port may just as well start from a - cut&paste of an existing port to a similar architecture (for - example from x86 to amd64, or from powerpc to sparc). - - The architecture specific code is split from the rest of the - JIT, for example the x86 specific code and data is all - included in the following files in the distribution: - - mini-x86.h mini-x86.c - inssel-x86.brg - cpu-pentium.md - tramp-x86.c - exceptions-x86.c - - I suggest a similar split for other architectures as well. - - Note that this document is still incomplete: some sections are - only sketched and some are missing, but the important info to - get a port going is already described. - - -* Architecture-specific instructions and instruction selection. - - The JIT already provides a set of instructions that can be - easily mapped to a great variety of different processor - instructions. Sometimes it may be necessary or advisable to - add a new instruction that represent more closely an - instruction in the architecture. Note that a mini instruction - can be used to represent also a short sequence of CPU - low-level instructions, but note that each instruction - represents the minimum amount of code the instruction - scheduler will handle (i.e., the scheduler won't schedule the - instructions that compose the low-level sequence as individual - instructions, but just the whole sequence, as an indivisible - block). - - New instructions are created by adding a line in the - mini-ops.h file, assigning an opcode and a name. To specify - the input and output for the instruction, there are two - different places, depending on the context in which the - instruction gets used. - - If the instruction is used in the tree representation, the - input and output types are defined by the BURG rules in the - *.brg files (the usual non-terminals are 'reg' to represent a - normal register, 'lreg' to represent a register or two that - hold a 64 bit value, freg for a floating point register). - - If an instruction is used as a low-level CPU instruction, the - info is specified in a machine description file. The - description file is processed by the genmdesc program to - provide a data structure that can be easily used from C code - to query the needed info about the instruction. - - As an example, let's consider the add instruction for both x86 - and ppc: - - x86 version: - add: dest:i src1:i src2:i len:2 clob:1 - ppc version: - add: dest:i src1:i src2:i len:4 - - Note that the instruction takes two input integer registers on - both CPU, but on x86 the first source register is clobbered - (clob:1) and the length in bytes of the instruction differs. - - Note that integer adds and floating point adds use different - opcodes, unlike the IL language (64 bit add is done with two - instructions on 32 bit architectures, using a add that sets - the carry and an add with carry). - - A specific CPU port may assign any meaning to the clob field - for an instruction since the value will be processed in an - arch-specific file anyway. - - See the top of the existing cpu-pentium.md file for more info - on other fields: the info may or may not be applicable to a - different CPU, in this latter case the info can be ignored. - - The code in mini.c together with the BURG rules in inssel.brg, - inssel-float.brg and inssel-long32.brg provides general - purpose mappings from the tree representation to a set of - instructions that should be easily implemented in any - architecture. To allow for additional arch-specific - functionality, an arch-specific BURG file can be used: in this - file arch-specific instructions can be selected that provide - better performance than the general instructions or that - provide functionality that is needed by the JIT but that - cannot be expressed in a general enough way. - - As an example, x86 has the special instruction "push" to make - it easier to implement the default call convention (passing - arguments on the stack): almost all the other architectures - don't have such an instruction (and don't need it anyway), so - we added a special rule in the inssel-x86.brg file for it. - - So, one of the first things needed in a port is to write a - cpu-$(arch).md machine description file and fill it with the - needed info. As a start, only a few instructions can be - specified, like the ones required to do simple integer - operations. The default rules of the instruction selector will - emit the common instructions and so we're ready to go for the - next step in porting the JIT. - - -*) Native code emission - - Since the first step in porting mono to a new CPU is to port - the interpreter, there should be already a file that allows - the emission of binary native code in a buffer for the - architecture. This file should be placed in the - - mono/arch/$(arch)/ - - directory. - - The bulk of the code emission happens in the mini-$(arch).c - file, in a function called mono_arch_output_basic_block - (). This function takes a basic block, walks the list of - instructions in the block and emits the binary code for each. - Optionally a peephole optimization pass is done on the basic - block, but this can be left for later, when the port actually - works. - - This function is very simple, there is just a big switch on - the instruction opcode and in the corresponding case the - functions or macros to emit the binary native code are - used. Note that in this function the lengths of the - instructions are used to determine if the buffer for the code - needs enlarging. - - To complete the code emission for a method, a few other - functions need implementing as well: - - mono_arch_emit_prolog () - mono_arch_emit_epilog () - mono_arch_patch_code () - - mono_arch_emit_prolog () will emit the code to setup the stack - frame for a method, optionally call the callbacks used in - profiling and tracing, and move the arguments to their home - location (in a caller-save register if the variable was - allocated to one, or in a stack location if the argument was - passed in a volatile register and wasn't allocated a - non-volatile one). caller-save registers used by the function - are saved in the prolog as well. - - mono_arch_emit_epilog () will emit the code needed to return - from the function, optionally calling the profiling or tracing - callbacks. At this point the basic blocks or the code that was - moved out of the normal flow for the function can be emitted - as well (this is usually done to provide better info for the - static branch predictor). In the epilog, caller-save - registers are restored if they were used. - - Note that, to help exception handling and stack unwinding, - when there is a transition from managed to unmanaged code, - some special processing needs to be done (basically, saving - all the registers and setting up the links in the Last Managed - Frame structure). - - When the epilog has been emitted, the upper level code - arranges for the buffer of memory that contains the native - code to be copied in an area of executable memory and at this - point, instructions that use relative addressing need to be - patched to have the right offsets: this work is done by - mono_arch_patch_code (). - - -* Call conventions and register allocation - - To account for the differences in the call conventions, a few functions need to - be implemented. - - mono_arch_allocate_vars () assigns to both arguments and local - variables the offset relative to the frame register where they - are stored, dead variables are simply discarded. The total - amount of stack needed is calculated. - - mono_arch_call_opcode () is the function that more closely - deals with the call convention on a given system. For each - argument to a function call, an instruction is created that - actually puts the argument where needed, be it the stack or a - specific register. This function can also re-arrange th order - of evaluation when multiple arguments are involved if needed - (like, on x86 arguments are pushed on the stack in reverse - order). The function needs to carefully take into accounts - platform specific issues, like how structures are returned as - well as the differences in size and/or alignment of managed - and corresponding unmanaged structures. - - The other chunk of code that needs to deal with the call - convention and other specifics of a CPU, is the local register - allocator, implemented in a function named - mono_arch_local_regalloc (). The local allocator deals with a - basic block at a time and basically just allocates registers - for temporary values during expression evaluation, spilling - and unspilling as necessary. - - The local allocator needs to take into account clobbering - information, both during simple instructions and during - function calls and it needs to deal with other - architecture-specific weirdnesses, like instructions that take - inputs only in specific registers or output only is some. - - Some effort will be put later in moving most of the local - register allocator to a common file so that the code can be - shared more for similar, risc-like CPUs. The register - allocator does a first pass on the instructions in a block, - collecting liveness information and in a backward pass on the - same list performs the actual register allocation, inserting - the instructions needed to spill values, if necessary. - - The cross-platform local register allocator is now implemented - and it is documented in the jit-regalloc file. - - When this part of code is implemented, some testing can be - done with the generated code for the new architecture. Most - helpful is the use of the --regression command line switch to - run the regression tests (basic.cs, for example). - - Note that the JIT will try to initialize the runtime, but it - may not be able yet to compile and execute complex code: - commenting most of the code in the mini_init() function in - mini.c is needed to let the JIT just compile the regression - tests. Also, using multiple -v switches on the command line - makes the JIT dump an increasing amount of information during - compilation. - - Values loaded into registers need to be extened as needed by - the ECMA specs: - - *) integers smaller than 4 bytes are extended to int32 values - *) 32 bit floats are extended to double precision (in particular - this means that currently all the floating point operations operate - on doubles) - -* Method trampolines - - To get better startup performance, the JIT actually compiles a - method only when needed. To achieve this, when a call to a - method is compiled, we actually emit a call to a magic - trampoline. The magic trampoline is a function written in - assembly that invokes the compiler to compile the given method - and jumps to the newly compiled code, ensuring the arguments - it received are passed correctly to the actual method. - - Before jumping to the new code, though, the magic trampoline - takes care of patching the call site so that next time the - call will go directly to the method instead of the - trampoline. How does this all work? - - mono_arch_create_jit_trampoline () creates a small function - that just preserves the arguments passed to it and adds an - additional argument (the method to compile) before calling the - generic trampoline. This small function is called the specific - trampoline, because it is method-specific (the method to - compile is hard-code in the instruction stream). - - The generic trampoline saves all the arguments that could get - clobbered and calls a C function that will do two things: - - *) actually call the JIT to compile the method - *) identify the calling code so that it can be patched to call directly - the actual method - - If the 'this' argument to a method is a boxed valuetype that - is passed to a method that expects just a pointer to the data, - an additional unboxing trampoline will need to be inserted as - well. - - -* Exception handling - - Exception handling is likely the most difficult part of the - port, as it needs to deal with unwinding (both managed and - unmanaged code) and calling catch and filter blocks. It also - needs to deal with signals, because mono takes advantage of - the MMU in the CPU and of the operation system to handle - dereferences of the NULL pointer. Some of the function needed - to implement the mechanisms are: - - mono_arch_get_throw_exception () returns a function that takes - an exception object and invokes an arch-specific function that - will enter the exception processing. To do so, all the - relevant registers need to be saved and passed on. - - mono_arch_handle_exception () this function takes the - exception thrown and a context that describes the state of the - CPU at the time the exception was thrown. The function needs - to implement the exception handling mechanism, so it makes a - search for an handler for the exception and if none is found, - it follows the unhandled exception path (that can print a - trace and exit or just abort the current thread). The - difficulty here is to unwind the stack correctly, by restoring - the register state at each call site in the call chain, - calling finally, filters and handler blocks while doing so. - - As part of exception handling a couple of internal calls need - to be implemented as well. - - ves_icall_get_frame_info () returns info about a specific - frame. - - mono_jit_walk_stack () walks the stack and calls a callback with info for - each frame found. - - ves_icall_get_trace () return an array of StackFrame objects. - -** Code generation for filter/finally handlers - - Filter and finally handlers are called from 2 different locations: - - 1.) from within the method containing the exception clauses - 2.) from the stack unwinding code - - To make this possible we implement them like subroutines, - ending with a "return" statement. The subroutine does not save - the base pointer, because we need access to the local - variables of the enclosing method. Its is possible that - instructions inside those handlers modify the stack pointer, - thus we save the stack pointer at the start of the handler, - and restore it at the end. We have to use a "call" instruction - to execute such finally handlers. - - The MIR code for filter and finally handlers looks like: - - OP_START_HANDLER - ... - OP_END_FINALLY | OP_ENDFILTER(reg) - - OP_START_HANDLER: should save the stack pointer somewhere - OP_END_FINALLY: restores the stack pointers and returns. - OP_ENDFILTER (reg): restores the stack pointers and returns the value in "reg". - -** Calling finally/filter handlers - - There is a special opcode to call those handler, its called - OP_CALL_HANDLER. It simple emits a call instruction. - - Its a bit more complex to call handler from outside (in the - stack unwinding code), because we have to restore the whole - context of the method first. After that we simply emit a call - instruction to invoke the handler. Its usually possible to use - the same code to call filter and finally handlers (see - arch_get_call_filter). - -** Calling catch handlers - - Catch handlers are always called from the stack unwinding - code. Unlike finally clauses or filters, catch handler never - return. Instead we simply restore the whole context, and - restart execution at the catch handler. - -** Passing Exception objects to catch handlers and filters. - - We use a local variable to store exception objects. The stack - unwinding code must store the exception object into this - variable before calling catch handler or filter. - -* Minor helper methods - - A few minor helper methods are referenced from the arch-independent code. - Some of them are: - - *) mono_arch_cpu_optimizations () - This function returns a mask of optimizations that - should be enabled for the current CPU and a mask of - optimizations that should be excluded, instead. - - *) mono_arch_regname () - Returns the name for a numeric register. - - *) mono_arch_get_allocatable_int_vars () - Returns a list of variables that can be allocated to - the integer registers in the current architecture. - - *) mono_arch_get_global_int_regs () - Returns a list of caller-save registers that can be - used to allocate variables in the current method. - - *) mono_arch_instrument_mem_needs () - *) mono_arch_instrument_prolog () - *) mono_arch_instrument_epilog () - Functions needed to implement the profiling interface. - -* Testing the port - - The JIT has a set of regression tests in *.cs files inside the - mini directory. - - The usual method of testing a port is by compiling these tests on - another machine with a working runtime by typing 'make rcheck', - then copying TestDriver.dll and *.exe to the mini directory. The - tests can be run by typing: - - ./mono --regression <exe file name> - - The suggested order for working through these tests is the - following: - - - basic.exe - - basic-long.exe - - basic-float.exe - - basic-calls.exe - - objects.exe - - arrays.exe - - exceptions.exe - - iltests.exe - - generics.exe - -* Writing regression tests - - Regression tests for the JIT should be written for any bug - found in the JIT in one of the *.cs files in the mini - directory. Eventually all the operations of the JIT should be - tested (including the ones that get selected only when some - specific optimization is enabled). - - -* Platform specific optimizations - - An example of a platform-specific optimization is the peephole - optimization: we look at a small window of code at a time and - we replace one or more instructions with others that perform - better for the given architecture or CPU. - -* 64 bit support tips, by Zoltan Varga (vargaz@gmail.com) - - For a 64-bit port of the Mono runtime, you will typically do - the following: - - * need to use inssel-long.brg instead of - inssel-long32.brg. - - * need to implement lots of new opcodes: - OP_I<OP> is 32 bit op - OP_L<OP> and CEE_<OP> are 64 bit ops - - - The 64 bit version of an existing port might share the code - with the 32 bit port (for example SPARC/SPARV9), or it might - be separate (x86/AMD64). - - That will depend on the similarities of the two instructions - sets/ABIs etc. - - The runtime and most parts of the JIT are 64 bit clean - at this point, so the only parts which require changing are - the arch dependent files. - -* Function descriptors - - Some ABIs, like those for IA64 and PPC64, don't use direct - function pointers, but so called function descriptors. A - function descriptor is a short data structure which contains - at least a pointer to the code of the function and a pointer - to a GOT/TOC, which needs to be loaded into a specific - register prior to jumping to the function. Global variables - and large constants are accessed through that register. - - Mono does not need function descriptors for the JITted code, - but we need to handle them when calling unmanaged code and we - need to create them when passing managed code to unmanaged - code. - - mono_create_ftnptr() creates a function descriptor for a piece - of generated code within a specific domain. - - mono_get_addr_from_ftnptr() returns the pointer to the native - code in a function descriptor. Never use this function to - generate a jump to a function without loading the GOT/TOC - register unless the function descriptor was created by - mono_create_ftnptr(). - - See the sources for IA64 and PPC64 on when to create and when - to dereference function descriptors. On PPC64 function - descriptors for various generated helper functions (in - exceptions-ppc.c and tramp-ppc.c) are generated in front of - the code they refer to (see ppc_create_pre_code_ftnptr()). On - IA64 they are created separately. - -* Emulated opcodes - - Mini has code for emulating quite a few opcodes, most notably - operations on longs, int/float conversions and atomic - operations. If an architecture wishes such an opcode to be - emulated, mini produces icalls instead of those opcodes. This - should only be considered when the operation cannot be - implemented efficiently and thus the overhead occured by the - icall is not relatively large. Emulation of operations is - controlled by #defines in the arch header, but the naming is - not consistent. They usually start with MONO_ARCH_EMULATE_, - MONO_ARCH_NO_EMULATE_ and MONO_ARCH_HAVE_. - -* Generic code sharing - - Generic code sharing is optional. See the file - "generic-sharing" for information on how to support it on an - architecture. |