xpcom/reflect/xptcall/porting.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/reflect/xptcall/porting.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,216 @@
     1.4 +<!-- This Source Code Form is subject to the terms of the Mozilla Public
     1.5 +   - License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 +   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
     1.7 +
     1.8 +<html>
     1.9 +<head>
    1.10 +<title>xptcall Porting Guide</title>
    1.11 +</head>
    1.12 +<body bgcolor = "white">
    1.13 +<h2><center>xptcall Porting Guide</center></h2>
    1.14 +
    1.15 +<h3>Overview</h3>
    1.16 +
    1.17 +<blockquote>
    1.18 +
    1.19 +<a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a> is a
    1.20 +library that supports both invoking methods on arbitrary xpcom objects and
    1.21 +implementing classes whose objects can impersonate any xpcom interface. It does
    1.22 +this using platform specific assembly language code. This code needs to be
    1.23 +ported to all platforms that want to support xptcall (and thus mozilla).
    1.24 +
    1.25 +</blockquote>
    1.26 +
    1.27 +<h3>The tree</h3>
    1.28 +
    1.29 +<blockquote>
    1.30 +<pre>
    1.31 +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a>
    1.32 +  +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a>  // exported headers
    1.33 +  +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a>  // core source
    1.34 +  |  \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md">md</a>  // platform specific parts
    1.35 +  |     +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/mac">mac</a>  // mac ppc
    1.36 +  |     +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a>  // all unix
    1.37 +  |     \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a>  // win32
    1.38 +  |     +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">test</a>  // simple tests to get started
    1.39 +  \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a>  // full tests via api
    1.40 +</pre>
    1.41 +
    1.42 +Porters are free to create subdirectories under the base <code>md</code>
    1.43 +directory for their given platforms and to integrate into the build system as
    1.44 +appropriate for their platform.
    1.45 +
    1.46 +</blockquote>
    1.47 +
    1.48 +<h3>Theory of operation</h3>
    1.49 +
    1.50 +<blockquote>
    1.51 +
    1.52 +There are really two pieces of functionality: <i>invoke</i> and <i>stubs</i>...
    1.53 +
    1.54 +<p>
    1.55 +
    1.56 +The <b><i>invoke</i></b> functionality requires the implementation of the
    1.57 +following on each platform (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h">xptcall/public/xptcall.h</a>):
    1.58 +
    1.59 +<pre>
    1.60 +XPTC_PUBLIC_API(nsresult)
    1.61 +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
    1.62 +                   uint32_t paramCount, nsXPTCVariant* params);
    1.63 +</pre>
    1.64 +
    1.65 +Calling code is expected to supply an array of <code>nsXPTCVariant</code>
    1.66 +structs. These are discriminated unions describing the type and value of each
    1.67 +parameter of the target function. The platform specific code then builds a call
    1.68 +frame and invokes the method indicated by the index <code>methodIndex</code> on
    1.69 +the xpcom interface <code>that</code>.
    1.70 +
    1.71 +<p>
    1.72 +
    1.73 +Here are examples of this implementation for 
    1.74 +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp">Win32</a>
    1.75 +and 
    1.76 +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>.
    1.77 +
    1.78 +Both of these implementations use the basic strategy of: figure out how much
    1.79 +stack space is needed for the params, make the space in a new frame, copy the
    1.80 +params to that space, invoke the method, cleanup and return. C++ is used where
    1.81 +appropriate, Assembly language is used where necessary. Inline assembly language is used here,
    1.82 +but it is equally valid to use separate assembly language source files. Porters
    1.83 +can decide how best to do this for their platforms.
    1.84 +
    1.85 +<p>
    1.86 +
    1.87 +The <b><i>stubs</i></b> functionality is more complex. The goal here is a class
    1.88 +whose vtbl can look like the vtbl of any arbitrary xpcom interface. Objects of
    1.89 +this class can then be built to impersonate any xpcom object. The base interface
    1.90 +for this is (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h">xptcall/public/xptcall.h</a>):
    1.91 +
    1.92 +<pre>
    1.93 +class nsXPTCStubBase : public nsISupports
    1.94 +{
    1.95 +public:
    1.96 +    // Include generated vtbl stub declarations.
    1.97 +    // These are virtual and *also* implemented by this class..
    1.98 +#include "xptcstubsdecl.inc"
    1.99 +
   1.100 +    // The following methods must be provided by inheritor of this class.
   1.101 +
   1.102 +    // return a refcounted pointer to the InterfaceInfo for this object
   1.103 +    // NOTE: on some platforms this MUST not fail or we crash!
   1.104 +    NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info) = 0;
   1.105 +
   1.106 +    // call this method and return result
   1.107 +    NS_IMETHOD CallMethod(uint16_t methodIndex,
   1.108 +                          const nsXPTMethodInfo* info,
   1.109 +                          nsXPTCMiniVariant* params) = 0;
   1.110 +};
   1.111 +</pre>
   1.112 +
   1.113 +Code that wishes to make use of this <i>stubs</i> functionality (such as 
   1.114 +<a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a class
   1.115 +which inherits from <code>nsXPTCStubBase</code> and implements the
   1.116 +<code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the
   1.117 +platform specific code know how to get interface information and how to dispatch methods
   1.118 +once their parameters have been pulled out of the platform specific calling
   1.119 +frame.
   1.120 +
   1.121 +<p>
   1.122 +
   1.123 +Porters of this functionality implement the platform specific code for the
   1.124 +<i>stub</i> methods that fill the vtbl for this class. The idea here is that the
   1.125 +class has a vtbl full of a large number of generic stubs. All instances of this
   1.126 +class share that vtbl and the same stubs. The stubs forward calls to a platform
   1.127 +specific method that uses the interface information supplied by
   1.128 +the overridden <code>GetInterfaceInfo</code> to extract the parameters and build
   1.129 +an array of platform independent <code>nsXPTCMiniVariant</code> structs which
   1.130 +are in turn passed on to the overridden <code>CallMethod</code>. The
   1.131 +platform dependent code is responsible for doing any cleanup and returning.
   1.132 +
   1.133 +<p>
   1.134 +
   1.135 +The stub methods are declared in <a
   1.136 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdecl.inc">xptcall/public/xptcstubsdecl.inc</a>.
   1.137 +These are '#included' into the declaration of <code>nsXPTCStubBase</code>. A
   1.138 +similar include file (<a
   1.139 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdef.inc">xptcall/public/xptcstubsdef.inc</a>)
   1.140 +is expanded using platform specific macros to define the stub functions. These
   1.141 +'.inc' files are checked into cvs. However, they can be regenerated as necessary
   1.142 +(i.e. to change the number of stubs or to change their specific declaration)
   1.143 +using the Perl script  <a
   1.144 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/genstubs.pl">xptcall/public/genstubs.pl</a>.
   1.145 +
   1.146 +<p>
   1.147 +
   1.148 +Here are examples of this implementation for  <a
   1.149 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp">Win32</a>
   1.150 +and  <a
   1.151 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>.
   1.152 +Both of these examples use inline assembly language. That is just how I
   1.153 +decided to do it. You can do it as you choose.
   1.154 +
   1.155 +<p>
   1.156 +
   1.157 +The Win32 version is somewhat tighter because the __declspec(naked) feature
   1.158 +allows for very small stubs. However, the __stdcall requires the callee to clean
   1.159 +up the stack, so it is imperative that the interface information scheme allow
   1.160 +the code to determine the correct stack pointer fixup for return without fail,
   1.161 +else the process will crash.
   1.162 +
   1.163 +<p>
   1.164 +
   1.165 +I opted to use inline assembler for the gcc Linux x86 port. I ended up with
   1.166 +larger stubs than I would have preferred rather than battle the compiler over
   1.167 +what would happen to the stack before my asm code began running.
   1.168 +
   1.169 +<p>
   1.170 +
   1.171 +I believe that the non-assembly parts of these files can be copied and reused
   1.172 +with minimal (but not zero) platform specific tweaks. Feel free to copy and
   1.173 +paste as necessary. Please remember that safety and reliability are more
   1.174 +important than speed optimizations. This code is primarily used to connect XPCOM
   1.175 +components with JavaScript; function call overhead is a <b>tiny</b> part of the
   1.176 +time involved.
   1.177 +
   1.178 +<p>
   1.179 +
   1.180 +I put together 
   1.181 +<a
   1.182 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">xptcall/src/md/test
   1.183 +</a> as a place to evolve the basic functionality as a port is coming together.
   1.184 +Not all of the functionality is exercised, but it is a place to get started. 
   1.185 +<a
   1.186 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">xptcall/tests
   1.187 +</a> has an api level test for <code>NS_InvokeByIndex</code>, but no tests for
   1.188 +the <i>stubs</i> functionality. Such a test ought to be written, but this has not
   1.189 +yet been done.
   1.190 +
   1.191 +<p>
   1.192 +
   1.193 +A full 'test' at this point requires building the client and running the
   1.194 +XPConnect test called <i>TestXPC</i> in
   1.195 +<a
   1.196 +href="http://lxr.mozilla.org/mozilla/source/js/xpconnect/tests">mozilla/js/xpconnect/tests
   1.197 +</a>.
   1.198 +
   1.199 +<p>
   1.200 +
   1.201 +Getting these ports done is very important. Please let <a
   1.202 +href="mailto:jband@netscape.com">me</a> know if you are interested in doing one.
   1.203 +I'll answer any questions as I get them.
   1.204 +
   1.205 +<p>
   1.206 +
   1.207 +<a
   1.208 +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html">
   1.209 +Porting Status
   1.210 +</a>
   1.211 +
   1.212 +</blockquote>
   1.213 +
   1.214 +<hr>
   1.215 +<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
   1.216 +<b>Last modified:</b> 31 May 1999
   1.217 +
   1.218 +</body>
   1.219 +</html>

mercurial