diff options
Diffstat (limited to 'xpcom/reflect/xptcall/porting.html')
-rw-r--r-- | xpcom/reflect/xptcall/porting.html | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/xpcom/reflect/xptcall/porting.html b/xpcom/reflect/xptcall/porting.html new file mode 100644 index 0000000000..a149aa144a --- /dev/null +++ b/xpcom/reflect/xptcall/porting.html @@ -0,0 +1,237 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<html> + <head> + <title>xptcall Porting Guide</title> + </head> + <body bgcolor="white"> + <h2><center>xptcall Porting Guide</center></h2> + + <h3>Overview</h3> + + <blockquote> + <a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a> + is a library that supports both invoking methods on arbitrary xpcom + objects and implementing classes whose objects can impersonate any xpcom + interface. It does this using platform specific assembly language code. + This code needs to be ported to all platforms that want to support xptcall + (and thus mozilla). + </blockquote> + + <h3>The tree</h3> + + <blockquote> + <pre> +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a> + +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a> // exported headers + +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a> // core source + | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md">md</a> // platform specific parts + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/mac">mac</a> // mac ppc + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> // all unix + | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a> // win32 + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test">test</a> // simple tests to get started + \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a> // full tests via api +</pre> + + Porters are free to create subdirectories under the base <code>md</code> + directory for their given platforms and to integrate into the build system + as appropriate for their platform. + </blockquote> + + <h3>Theory of operation</h3> + + <blockquote> + There are really two pieces of functionality: <i>invoke</i> and + <i>stubs</i>... + + <p> + The <b><i>invoke</i></b> functionality requires the implementation of + the following on each platform (from + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h" + >xptcall/xptcall.h</a + >): + </p> + + <pre> +XPTC_PUBLIC_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); +</pre + > + + Calling code is expected to supply an array of + <code>nsXPTCVariant</code> structs. These are discriminated unions + describing the type and value of each parameter of the target function. + The platform specific code then builds a call frame and invokes the method + indicated by the index <code>methodIndex</code> on the xpcom interface + <code>that</code>. + + <p> + Here are examples of this implementation for + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp" + >Win32</a + > + and + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcinvoke_unixish_x86.cpp" + >Linux x86, NetBSD x86, and FreeBSD</a + >. Both of these implementations use the basic strategy of: figure out + how much stack space is needed for the params, make the space in a new + frame, copy the params to that space, invoke the method, cleanup and + return. C++ is used where appropriate, Assembly language is used where + necessary. Inline assembly language is used here, but it is equally + valid to use separate assembly language source files. Porters can decide + how best to do this for their platforms. + </p> + + <p> + The <b><i>stubs</i></b> functionality is more complex. The goal here is + a class whose vtbl can look like the vtbl of any arbitrary xpcom + interface. Objects of this class can then be built to impersonate any + xpcom object. The base interface for this is (from + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h" + >xptcall/xptcall.h</a + >): + </p> + + <pre> +class nsXPTCStubBase : public nsISupports +{ +public: + // Include generated vtbl stub declarations. + // These are virtual and *also* implemented by this class.. +#include "xptcstubsdecl.inc" + + // The following methods must be provided by inheritor of this class. + + // return a refcounted pointer to the InterfaceInfo for this object + // NOTE: on some platforms this MUST not fail or we crash! + NS_IMETHOD GetInterfaceInfo(const nsXPTInterfaceInfo** info) = 0; + + // call this method and return result + NS_IMETHOD CallMethod(uint16_t methodIndex, + const nsXPTMethodInfo* info, + nsXPTCMiniVariant* params) = 0; +}; +</pre + > + + Code that wishes to make use of this <i>stubs</i> functionality (such as + <a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a + class which inherits from <code>nsXPTCStubBase</code> and implements the + <code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the + platform specific code know how to get interface information and how to + dispatch methods once their parameters have been pulled out of the + platform specific calling frame. + + <p> + Porters of this functionality implement the platform specific code for + the + <i>stub</i> methods that fill the vtbl for this class. The idea here is + that the class has a vtbl full of a large number of generic stubs. All + instances of this class share that vtbl and the same stubs. The stubs + forward calls to a platform specific method that uses the interface + information supplied by the overridden <code>GetInterfaceInfo</code> to + extract the parameters and build an array of platform independent + <code>nsXPTCMiniVariant</code> structs which are in turn passed on to + the overridden <code>CallMethod</code>. The platform dependent code is + responsible for doing any cleanup and returning. + </p> + + <p> + The stub methods are declared in + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdecl.inc" + >xptcall/xptcstubsdecl.inc</a + >. These are '#included' into the declaration of + <code>nsXPTCStubBase</code>. A similar include file (<a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdef.inc" + >xptcall/xptcstubsdef.inc</a + >) is expanded using platform specific macros to define the stub + functions. These '.inc' files are checked into cvs. However, they can be + regenerated as necessary (i.e. to change the number of stubs or to + change their specific declaration) using the Perl script + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/genstubs.pl" + >xptcall/genstubs.pl</a + >. + </p> + + <p> + Here are examples of this implementation for + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp" + >Win32</a + > + and + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcstubs_unixish_x86.cpp" + >Linux x86, NetBSD x86, and FreeBSD</a + >. Both of these examples use inline assembly language. That is just how + I decided to do it. You can do it as you choose. + </p> + + <p> + The Win32 version is somewhat tighter because the __declspec(naked) + feature allows for very small stubs. However, the __stdcall requires the + callee to clean up the stack, so it is imperative that the interface + information scheme allow the code to determine the correct stack pointer + fixup for return without fail, else the process will crash. + </p> + + <p> + I opted to use inline assembler for the gcc Linux x86 port. I ended up + with larger stubs than I would have preferred rather than battle the + compiler over what would happen to the stack before my asm code began + running. + </p> + + <p> + I believe that the non-assembly parts of these files can be copied and + reused with minimal (but not zero) platform specific tweaks. Feel free + to copy and paste as necessary. Please remember that safety and + reliability are more important than speed optimizations. This code is + primarily used to connect XPCOM components with JavaScript; function + call overhead is a <b>tiny</b> part of the time involved. + </p> + + <p> + I put together + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test" + >xptcall/md/test + </a> + as a place to evolve the basic functionality as a port is coming + together. Not all of the functionality is exercised, but it is a place + to get started. + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests" + >xptcall/tests + </a> + has an api level test for <code>NS_InvokeByIndex</code>, but no tests + for the <i>stubs</i> functionality. Such a test ought to be written, but + this has not yet been done. + </p> + + <p> + A full 'test' at this point requires building the client and running the + XPConnect test called <i>TestXPC</i> in + <a href="http://lxr.mozilla.org/mozilla/source/js/xpconnect/tests" + >mozilla/js/xpconnect/tests </a + >. + </p> + </blockquote> + + <hr /> + <b>Author:</b> + <a href="mailto:jband@netscape.com" + >John Bandhauer <jband@netscape.com></a + ><br /> + <b>Last modified:</b> 31 May 1999 + </body> +</html> |