Tamarin:Porting: Difference between revisions
| Line 72: | Line 72: | ||
Another advantage of this method is to avoid platform ifdefs around the #include blocks. The includes would be defined in each platform's portingapi_<module>.h file. | Another advantage of this method is to avoid platform ifdefs around the #include blocks. The includes would be defined in each platform's portingapi_<module>.h file. | ||
= Posix/stdlib functions = | |||
Currently, all of the supported platforms have implementations of the common posix/stdlib functions such as alloca, malloc, fopen, fwrite, memcpy, memset, etc., but in some cases these are provided through an additional framework or shim layer and less efficient than calling the equivalent native API functions. Also, some platforms have no implementation of some or all of these functions. In order to support more platforms and to increase efficiency on some others, a next step would be to replace the direct calls to these functions with the same type of macros. | Currently, all of the supported platforms have implementations of the common posix/stdlib functions such as alloca, malloc, fopen, fwrite, memcpy, memset, etc., but in some cases these are provided through an additional framework or shim layer and less efficient than calling the equivalent native API functions. Also, some platforms have no implementation of some or all of these functions. In order to support more platforms and to increase efficiency on some others, a next step would be to replace the direct calls to these functions with the same type of macros. | ||
Revision as of 18:42, 9 July 2008
Goals
A goal of Tamarin is to allow it to run on any platform, to this end we wish to create a standardized porting layer that is:
- lightweight
- simple
Details
An abstraction layer can solve the portability issue, but at the cost of speed, stack and code size. In order to avoid this overhead, we usually add platform specific ifdefs, e.g.
#if defined(WIN32)
#if defined(UNDER_CE)
WindowsCEAPIFunction();
#else
WindowsAPIFunction();
#elsif defined(MAC)
MacOSAPIFunction();
#elsif defined(LINUX)
LinuxAPIFunction();
#endif
The resulting code is efficient, but can be difficult to read and since the platform dependencies are often scattered throughout the code, porting to a new platform will require changes across files throughout the codebase.
The proposed solution is to define sets of macros that replace the platform specific ifdefs with a single macro that is defined in a central location. For example for many platforms newly JITted code requires that the instruction cache be flushed. The resulting code would look something like this:
#if defined(WIN32)
#if defined(UNDER_CE)
FlushInstructionCache(GetCurrentProcess(), NULL, NULL); // Windows CE
#else
// Not required on Windows, assuming P5 or later.
#endif
#elsif defined(AVMPLUS_LINUX)
#if defined(AVMPLUS_ARM)
// some code plus inline assembler
#else
// not required for x86 Linux
#endif
#elsif defined(AVMPLUS_SYMBIAN)
User::IMB_Range(start, end);
#endif
The proposal is to replace that block of code with the following macro
NanoJIT_PortAPI_FlushInstructionCache(start, end);
Where the macro is defined for each platform. For x86 platforms, it is defined as nothing. For ARM platforms, it is defined as the appropriate system call, a function that implements the functionality, or some inline code.
Each platform would have its own set of header files where these macros are defined. For clarity, it would be best to divide the macros by module. The current proposal is to have one file for each of
- MMgc
- NanoJIT
- other modules
For example, the header file for the NanoJIT (portingapi_nanojit.h) would look like this for Win32/x86:
// no-op. not required for P5 or later. #define NanoJIT_PortAPI_FlushInstructionCache(_start, _end)
For WinCE/ARM:
#define NanoJIT_PortAPI_FlushInstructionCache(_start, _end) FlushInstructionCache(GetCurrentProcess(), _start, (_end - _start))
For Symbian:
#include <e32std.h> #define NanoJIT_PortAPI_FlushInstructionCache(_start, _end) User::IMB_Range(_start, _end)
For some hypothetical platform that requires an implementation that is more than one line and best implemented in a functon:
#include <somefile.h> extern void NanoJIT_PortAPI_FlushInstructionCache_Impl(void*, void*); #define NanoJIT_PortAPI_FlushInstructionCache(_start, _end) NanoJIT_PortAPI_FlushInstructionCache_Impl(_start, _end)
Another advantage of this method is to avoid platform ifdefs around the #include blocks. The includes would be defined in each platform's portingapi_<module>.h file.
Posix/stdlib functions
Currently, all of the supported platforms have implementations of the common posix/stdlib functions such as alloca, malloc, fopen, fwrite, memcpy, memset, etc., but in some cases these are provided through an additional framework or shim layer and less efficient than calling the equivalent native API functions. Also, some platforms have no implementation of some or all of these functions. In order to support more platforms and to increase efficiency on some others, a next step would be to replace the direct calls to these functions with the same type of macros.