xpcom/reflect/xptcall/porting.html

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 <!-- This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 - License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
michael@0 4
michael@0 5 <html>
michael@0 6 <head>
michael@0 7 <title>xptcall Porting Guide</title>
michael@0 8 </head>
michael@0 9 <body bgcolor = "white">
michael@0 10 <h2><center>xptcall Porting Guide</center></h2>
michael@0 11
michael@0 12 <h3>Overview</h3>
michael@0 13
michael@0 14 <blockquote>
michael@0 15
michael@0 16 <a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a> is a
michael@0 17 library that supports both invoking methods on arbitrary xpcom objects and
michael@0 18 implementing classes whose objects can impersonate any xpcom interface. It does
michael@0 19 this using platform specific assembly language code. This code needs to be
michael@0 20 ported to all platforms that want to support xptcall (and thus mozilla).
michael@0 21
michael@0 22 </blockquote>
michael@0 23
michael@0 24 <h3>The tree</h3>
michael@0 25
michael@0 26 <blockquote>
michael@0 27 <pre>
michael@0 28 <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a>
michael@0 29 +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a> // exported headers
michael@0 30 +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a> // core source
michael@0 31 | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md">md</a> // platform specific parts
michael@0 32 | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/mac">mac</a> // mac ppc
michael@0 33 | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> // all unix
michael@0 34 | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a> // win32
michael@0 35 | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">test</a> // simple tests to get started
michael@0 36 \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a> // full tests via api
michael@0 37 </pre>
michael@0 38
michael@0 39 Porters are free to create subdirectories under the base <code>md</code>
michael@0 40 directory for their given platforms and to integrate into the build system as
michael@0 41 appropriate for their platform.
michael@0 42
michael@0 43 </blockquote>
michael@0 44
michael@0 45 <h3>Theory of operation</h3>
michael@0 46
michael@0 47 <blockquote>
michael@0 48
michael@0 49 There are really two pieces of functionality: <i>invoke</i> and <i>stubs</i>...
michael@0 50
michael@0 51 <p>
michael@0 52
michael@0 53 The <b><i>invoke</i></b> functionality requires the implementation of the
michael@0 54 following on each platform (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h">xptcall/public/xptcall.h</a>):
michael@0 55
michael@0 56 <pre>
michael@0 57 XPTC_PUBLIC_API(nsresult)
michael@0 58 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
michael@0 59 uint32_t paramCount, nsXPTCVariant* params);
michael@0 60 </pre>
michael@0 61
michael@0 62 Calling code is expected to supply an array of <code>nsXPTCVariant</code>
michael@0 63 structs. These are discriminated unions describing the type and value of each
michael@0 64 parameter of the target function. The platform specific code then builds a call
michael@0 65 frame and invokes the method indicated by the index <code>methodIndex</code> on
michael@0 66 the xpcom interface <code>that</code>.
michael@0 67
michael@0 68 <p>
michael@0 69
michael@0 70 Here are examples of this implementation for
michael@0 71 <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp">Win32</a>
michael@0 72 and
michael@0 73 <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>.
michael@0 74
michael@0 75 Both of these implementations use the basic strategy of: figure out how much
michael@0 76 stack space is needed for the params, make the space in a new frame, copy the
michael@0 77 params to that space, invoke the method, cleanup and return. C++ is used where
michael@0 78 appropriate, Assembly language is used where necessary. Inline assembly language is used here,
michael@0 79 but it is equally valid to use separate assembly language source files. Porters
michael@0 80 can decide how best to do this for their platforms.
michael@0 81
michael@0 82 <p>
michael@0 83
michael@0 84 The <b><i>stubs</i></b> functionality is more complex. The goal here is a class
michael@0 85 whose vtbl can look like the vtbl of any arbitrary xpcom interface. Objects of
michael@0 86 this class can then be built to impersonate any xpcom object. The base interface
michael@0 87 for this is (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h">xptcall/public/xptcall.h</a>):
michael@0 88
michael@0 89 <pre>
michael@0 90 class nsXPTCStubBase : public nsISupports
michael@0 91 {
michael@0 92 public:
michael@0 93 // Include generated vtbl stub declarations.
michael@0 94 // These are virtual and *also* implemented by this class..
michael@0 95 #include "xptcstubsdecl.inc"
michael@0 96
michael@0 97 // The following methods must be provided by inheritor of this class.
michael@0 98
michael@0 99 // return a refcounted pointer to the InterfaceInfo for this object
michael@0 100 // NOTE: on some platforms this MUST not fail or we crash!
michael@0 101 NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info) = 0;
michael@0 102
michael@0 103 // call this method and return result
michael@0 104 NS_IMETHOD CallMethod(uint16_t methodIndex,
michael@0 105 const nsXPTMethodInfo* info,
michael@0 106 nsXPTCMiniVariant* params) = 0;
michael@0 107 };
michael@0 108 </pre>
michael@0 109
michael@0 110 Code that wishes to make use of this <i>stubs</i> functionality (such as
michael@0 111 <a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a class
michael@0 112 which inherits from <code>nsXPTCStubBase</code> and implements the
michael@0 113 <code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the
michael@0 114 platform specific code know how to get interface information and how to dispatch methods
michael@0 115 once their parameters have been pulled out of the platform specific calling
michael@0 116 frame.
michael@0 117
michael@0 118 <p>
michael@0 119
michael@0 120 Porters of this functionality implement the platform specific code for the
michael@0 121 <i>stub</i> methods that fill the vtbl for this class. The idea here is that the
michael@0 122 class has a vtbl full of a large number of generic stubs. All instances of this
michael@0 123 class share that vtbl and the same stubs. The stubs forward calls to a platform
michael@0 124 specific method that uses the interface information supplied by
michael@0 125 the overridden <code>GetInterfaceInfo</code> to extract the parameters and build
michael@0 126 an array of platform independent <code>nsXPTCMiniVariant</code> structs which
michael@0 127 are in turn passed on to the overridden <code>CallMethod</code>. The
michael@0 128 platform dependent code is responsible for doing any cleanup and returning.
michael@0 129
michael@0 130 <p>
michael@0 131
michael@0 132 The stub methods are declared in <a
michael@0 133 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdecl.inc">xptcall/public/xptcstubsdecl.inc</a>.
michael@0 134 These are '#included' into the declaration of <code>nsXPTCStubBase</code>. A
michael@0 135 similar include file (<a
michael@0 136 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdef.inc">xptcall/public/xptcstubsdef.inc</a>)
michael@0 137 is expanded using platform specific macros to define the stub functions. These
michael@0 138 '.inc' files are checked into cvs. However, they can be regenerated as necessary
michael@0 139 (i.e. to change the number of stubs or to change their specific declaration)
michael@0 140 using the Perl script <a
michael@0 141 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/genstubs.pl">xptcall/public/genstubs.pl</a>.
michael@0 142
michael@0 143 <p>
michael@0 144
michael@0 145 Here are examples of this implementation for <a
michael@0 146 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp">Win32</a>
michael@0 147 and <a
michael@0 148 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>.
michael@0 149 Both of these examples use inline assembly language. That is just how I
michael@0 150 decided to do it. You can do it as you choose.
michael@0 151
michael@0 152 <p>
michael@0 153
michael@0 154 The Win32 version is somewhat tighter because the __declspec(naked) feature
michael@0 155 allows for very small stubs. However, the __stdcall requires the callee to clean
michael@0 156 up the stack, so it is imperative that the interface information scheme allow
michael@0 157 the code to determine the correct stack pointer fixup for return without fail,
michael@0 158 else the process will crash.
michael@0 159
michael@0 160 <p>
michael@0 161
michael@0 162 I opted to use inline assembler for the gcc Linux x86 port. I ended up with
michael@0 163 larger stubs than I would have preferred rather than battle the compiler over
michael@0 164 what would happen to the stack before my asm code began running.
michael@0 165
michael@0 166 <p>
michael@0 167
michael@0 168 I believe that the non-assembly parts of these files can be copied and reused
michael@0 169 with minimal (but not zero) platform specific tweaks. Feel free to copy and
michael@0 170 paste as necessary. Please remember that safety and reliability are more
michael@0 171 important than speed optimizations. This code is primarily used to connect XPCOM
michael@0 172 components with JavaScript; function call overhead is a <b>tiny</b> part of the
michael@0 173 time involved.
michael@0 174
michael@0 175 <p>
michael@0 176
michael@0 177 I put together
michael@0 178 <a
michael@0 179 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">xptcall/src/md/test
michael@0 180 </a> as a place to evolve the basic functionality as a port is coming together.
michael@0 181 Not all of the functionality is exercised, but it is a place to get started.
michael@0 182 <a
michael@0 183 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">xptcall/tests
michael@0 184 </a> has an api level test for <code>NS_InvokeByIndex</code>, but no tests for
michael@0 185 the <i>stubs</i> functionality. Such a test ought to be written, but this has not
michael@0 186 yet been done.
michael@0 187
michael@0 188 <p>
michael@0 189
michael@0 190 A full 'test' at this point requires building the client and running the
michael@0 191 XPConnect test called <i>TestXPC</i> in
michael@0 192 <a
michael@0 193 href="http://lxr.mozilla.org/mozilla/source/js/xpconnect/tests">mozilla/js/xpconnect/tests
michael@0 194 </a>.
michael@0 195
michael@0 196 <p>
michael@0 197
michael@0 198 Getting these ports done is very important. Please let <a
michael@0 199 href="mailto:jband@netscape.com">me</a> know if you are interested in doing one.
michael@0 200 I'll answer any questions as I get them.
michael@0 201
michael@0 202 <p>
michael@0 203
michael@0 204 <a
michael@0 205 href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html">
michael@0 206 Porting Status
michael@0 207 </a>
michael@0 208
michael@0 209 </blockquote>
michael@0 210
michael@0 211 <hr>
michael@0 212 <b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
michael@0 213 <b>Last modified:</b> 31 May 1999
michael@0 214
michael@0 215 </body>
michael@0 216 </html>

mercurial