<div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Ken,<div><br></div><div> this all looks fine. I see one minor slip. You're supplied</div><div><br></div><div><div>ThreadedFFICalloutStateForARM64>>instVarNamesAndTypesForTranslationDo: aBinaryBlock</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>"enumerate aBinaryBlock with the names and C type strings for the inst vars to include in a ThreadedFFICalloutState struct."</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>superclass instVarNamesAndTypesForTranslationDo: aBinaryBlock.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>self instVarNames do:</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>[:ivn|</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>aBinaryBlock</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>value: ivn</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>value: (ivn caseOf: {</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>['integerRegisters']<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>-> [{#sqLong. '[NumIntRegArgs]'}].</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>['floatRegisters']<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>-> [{#double. '[NumFloatRegArgs]'}] }</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>otherwise:</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>[#sqLong])]</div></div><div><br></div><div>which differs from the 32-bit ARM one in using double vs float and sqLong vs sqInt. Using double vs long is correct. But using sqLong is unnecessary, since in 64-bits saint is equal to sqLong, so I would have written it using saint instead. But it's fine as is. I just wanted you to know that in 64-bits sqInt must be a signed 64-bit type (at least in the VMMaker.oscog fork).</div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jan 20, 2019 at 6:40 PM <<a href="mailto:commits@source.squeak.org">commits@source.squeak.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"> <br>
Eliot Miranda uploaded a new version of VMMaker to project VM Maker Inbox:<br>
<a href="http://source.squeak.org/VMMakerInbox/VMMaker.oscog-KenD.2509.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMakerInbox/VMMaker.oscog-KenD.2509.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-KenD.2509<br>
Author: KenD<br>
Time: 20 January 2019, 7:38:17.915054 pm<br>
UUID: adac22d0-d981-4329-85ee-a8cf5647f645<br>
Ancestors: VMMaker.oscog-eem.2508<br>
<br>
Saved Progress in arm64ffi<br>
<br>
=============== Diff against VMMaker.oscog-eem.2508 ===============<br>
<br>
Item was changed:<br>
----- Method: RiscOSVMMaker class>>generateSqueakStackVM (in category 'configurations') -----<br>
generateSqueakStackVM<br>
"RISC OS version; build needed plugins, make sure filename tweaking is used"<br>
"RiscOSVMMaker generateSqueakStackVM"<br>
^self<br>
generate: StackInterpreter<br>
to: (FileDirectory default directoryNamed: 'stacksrc') fullName<br>
platformDir: (FileDirectory default directoryNamed: 'platforms') fullName<br>
+ excluding: #(AsynchFilePlugin BrokenPlugin CroquetPlugin FFIPlugin IA32ABIPlugin ImmX11Plugin InternetConfigPlugin JoystickTabletPlugin MIDIPlugin MacMenubarPlugin Mpeg3Plugin NewsqueakIA32ABIPlugin QuicktimePlugin SerialPlugin TestOSAPlugin ThreadedARMFFIPlugin ThreadedARMFFI64Plugin ThreadedFFIPlugin ThreadedIA32FFIPlugin ThreadedPPCBEFFIPlugin UUIDPlugin VMProfileMacSupportPlugin)!<br>
- excluding: #(AsynchFilePlugin BrokenPlugin CroquetPlugin FFIPlugin IA32ABIPlugin ImmX11Plugin InternetConfigPlugin JoystickTabletPlugin MIDIPlugin MacMenubarPlugin Mpeg3Plugin NewsqueakIA32ABIPlugin QuicktimePlugin SerialPlugin TestOSAPlugin ThreadedARMFFIPlugin ThreadedFFIPlugin ThreadedIA32FFIPlugin ThreadedPPCBEFFIPlugin UUIDPlugin VMProfileMacSupportPlugin)!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin class>>calloutStateClass (in category 'translation') -----<br>
+ calloutStateClass<br>
+ ^ThreadedFFICalloutStateForARM64!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin>>ffiPushDoubleFloat:in: (in category 'marshalling') -----<br>
+ ffiPushDoubleFloat: value in: calloutState<br>
+ <var: #value type: #double><br>
+ <var: #calloutState type: #'CalloutState *'><br>
+ <inline: #always><br>
+ <br>
+ calloutState floatRegisterIndex < (NumFloatRegArgs - 1)<br>
+ ifTrue:<br>
+ [(self cCoerceSimple: <br>
+ (self addressOf: (calloutState floatRegisters at: calloutState floatRegisterIndex)) <br>
+ to: 'double*')<br>
+ at: 0<br>
+ put: value.<br>
+ calloutState floatRegisterIndex: calloutState floatRegisterIndex + 2]<br>
+ ifFalse:<br>
+ [calloutState currentArg + self wordSize > calloutState limit ifTrue:<br>
+ [^FFIErrorCallFrameTooBig].<br>
+ calloutState floatRegisterIndex: NumFloatRegArgs.<br>
+ interpreterProxy storeFloatAtPointer: calloutState currentArg from: value.<br>
+ calloutState currentArg: calloutState currentArg + self wordSize].<br>
+ ^0!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin>>ffiPushSignedInt:in: (in category 'marshalling') -----<br>
+ ffiPushSignedInt: value in: calloutState<br>
+ <var: #calloutState type: #'CalloutState *'><br>
+ <inline: true><br>
+ calloutState integerRegisterIndex < NumIntRegArgs<br>
+ ifTrue:<br>
+ [calloutState integerRegisters <br>
+ at: calloutState integerRegisterIndex <br>
+ put: (self cCoerceSimple: value to: #sqLong).<br>
+ calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
+ ifFalse:<br>
+ [calloutState currentArg + self wordSize > calloutState limit ifTrue:<br>
+ [^FFIErrorCallFrameTooBig].<br>
+ interpreterProxy longAt: calloutState currentArg put: value.<br>
+ calloutState currentArg: calloutState currentArg + self wordSize].<br>
+ ^0<br>
+ !<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin>>ffiPushSignedLongLong:in: (in category 'marshalling') -----<br>
+ ffiPushSignedLongLong: value in: calloutState<br>
+ <var: #value type: #sqLong><br>
+ <var: #calloutState type: #'CalloutState *'><br>
+ <inline: true><br>
+ calloutState integerRegisterIndex < NumIntRegArgs<br>
+ ifTrue:<br>
+ [calloutState integerRegisters <br>
+ at: calloutState integerRegisterIndex <br>
+ put: (self cCoerceSimple: value to: #sqLong).<br>
+ calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
+ ifFalse:<br>
+ [calloutState currentArg + self wordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].<br>
+ interpreterProxy longAt: calloutState currentArg put: value.<br>
+ calloutState currentArg: calloutState currentArg + self wordSize].<br>
+ ^0!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin>>ffiPushSingleFloat:in: (in category 'marshalling') -----<br>
+ ffiPushSingleFloat: value in: calloutState<br>
+ <var: #value type: #float><br>
+ <var: #calloutState type: #'CalloutState *'><br>
+ <inline: #always><br>
+ calloutState floatRegisterIndex < NumFloatRegArgs<br>
+ ifTrue: <br>
+ [calloutState floatRegisters <br>
+ at: calloutState floatRegisterIndex <br>
+ put: (self cCoerceSimple: value to: #double).<br>
+ calloutState floatRegisterIndex: calloutState floatRegisterIndex + 2]<br>
+ ifFalse:<br>
+ [calloutState currentArg + self wordSize > calloutState limit ifTrue:<br>
+ [^FFIErrorCallFrameTooBig].<br>
+ interpreterProxy storeSingleFloatAtPointer: calloutState currentArg from: value.<br>
+ calloutState currentArg: calloutState currentArg + self wordSize].<br>
+ ^0!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin>>ffiPushStructure:ofSize:typeSpec:ofLength:in: (in category 'marshalling') -----<br>
+ ffiPushStructure: pointer ofSize: structSize typeSpec: argSpec ofLength: argSpecSize in: calloutState<br>
+ <var: #pointer type: #'void *'><br>
+ <var: #argSpec type: #'sqInt *'><br>
+ <var: #calloutState type: #'CalloutState *'><br>
+ <inline: true><br>
+ | availableRegisterSpace stackPartSize roundedSize |<br>
+ <br>
+ availableRegisterSpace := (NumIntRegArgs - calloutState integerRegisterIndex) * self wordSize.<br>
+ stackPartSize := structSize.<br>
+ availableRegisterSpace > 0<br>
+ ifTrue: <br>
+ [structSize <= availableRegisterSpace<br>
+ ifTrue:<br>
+ ["all in registers"<br>
+ stackPartSize := 0.<br>
+ self <br>
+ memcpy: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: 'void *') <br>
+ _: pointer <br>
+ _: structSize.<br>
+ calloutState integerRegisterIndex: calloutState integerRegisterIndex + (structSize + 3 bitShift: -2) ]<br>
+ ifFalse:<br>
+ ["If no previous co-processor candidate arg has already been pushed on the stack, then split the struct between registers and stack.<br>
+ Otherwise push entire struct on stack."<br>
+ calloutState currentArg = calloutState argVector<br>
+ ifTrue: <br>
+ [stackPartSize := structSize - availableRegisterSpace.<br>
+ self <br>
+ memcpy: (self cCoerceSimple: (self addressOf: (calloutState integerRegisters at: calloutState integerRegisterIndex)) to: 'void *') <br>
+ _: pointer <br>
+ _: availableRegisterSpace]<br>
+ ifFalse:<br>
+ [availableRegisterSpace := 0].<br>
+ calloutState integerRegisterIndex: NumIntRegArgs]].<br>
+ <br>
+ stackPartSize > 0<br>
+ ifTrue: <br>
+ [roundedSize := stackPartSize + 3 bitClear: 3.<br>
+ calloutState currentArg + roundedSize > calloutState limit ifTrue:<br>
+ [^FFIErrorCallFrameTooBig].<br>
+ self memcpy: calloutState currentArg _: (self addressOf: ((self cCoerceSimple: pointer to: 'char *') at: availableRegisterSpace)) _: stackPartSize.<br>
+ calloutState currentArg: calloutState currentArg + roundedSize].<br>
+ ^0!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin>>ffiPushUnsignedInt:in: (in category 'marshalling') -----<br>
+ ffiPushUnsignedInt: value in: calloutState<br>
+ <var: #calloutState type: #'CalloutState *'><br>
+ <inline: true><br>
+ calloutState integerRegisterIndex < NumIntRegArgs<br>
+ ifTrue:<br>
+ [calloutState integerRegisters <br>
+ at: calloutState integerRegisterIndex <br>
+ put: (self cCoerceSimple: value to: #usqLong).<br>
+ calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
+ ifFalse:<br>
+ [calloutState currentArg + self wordSize > calloutState limit ifTrue:<br>
+ [^FFIErrorCallFrameTooBig].<br>
+ interpreterProxy longAt: calloutState currentArg put: value.<br>
+ calloutState currentArg: calloutState currentArg + self wordSize].<br>
+ ^0<br>
+ <br>
+ !<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedARM64FFIPlugin>>ffiPushUnsignedLongLong:in: (in category 'marshalling') -----<br>
+ ffiPushUnsignedLongLong: value in: calloutState<br>
+ <var: #value type: #usqLong><br>
+ <var: #calloutState type: #'CalloutState *'><br>
+ <inline: true><br>
+ calloutState integerRegisterIndex < NumIntRegArgs<br>
+ ifTrue:<br>
+ [calloutState integerRegisters <br>
+ at: calloutState integerRegisterIndex <br>
+ put:(self cCoerceSimple: value to: #usqLong).<br>
+ calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1]<br>
+ ifFalse:<br>
+ [calloutState currentArg + self wordSize > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig].<br>
+ interpreterProxy longAt: calloutState currentArg put: value.<br>
+ calloutState currentArg: calloutState currentArg + self wordSize].<br>
+ ^0<br>
+ !<br>
<br>
Item was added:<br>
+ ThreadedFFICalloutStateForARM subclass: #ThreadedFFICalloutStateForARM64<br>
+ instanceVariableNames: ''<br>
+ classVariableNames: ''<br>
+ poolDictionaries: ''<br>
+ category: 'VMMaker-Plugins-FFI'!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForARM64 class>>instVarNamesAndTypesForTranslationDo: (in category 'translation') -----<br>
+ instVarNamesAndTypesForTranslationDo: aBinaryBlock<br>
+ "enumerate aBinaryBlock with the names and C type strings for the inst vars to include in a ThreadedFFICalloutState struct."<br>
+ <br>
+ superclass instVarNamesAndTypesForTranslationDo: aBinaryBlock.<br>
+ self instVarNames do:<br>
+ [:ivn|<br>
+ aBinaryBlock<br>
+ value: ivn<br>
+ value: (ivn caseOf: {<br>
+ ['integerRegisters'] -> [{#sqLong. '[NumIntRegArgs]'}].<br>
+ ['floatRegisters'] -> [{#double. '[NumFloatRegArgs]'}] }<br>
+ otherwise:<br>
+ [#sqLong])]!<br>
<br>
Item was added:<br>
+ ----- Method: ThreadedFFICalloutStateForARM64>>initialize (in category 'initialize-release') -----<br>
+ initialize<br>
+ super initialize.<br>
+ "Override with proper # regs"<br>
+ integerRegisters := CArrayAccessor on: (Array new: ThreadedARM64FFIPlugin numIntRegArgs).<br>
+ floatRegisters := CArrayAccessor on: (Array new: ThreadedARM64FFIPlugin numFloatRegArgs)!<br>
<br>
Item was changed:<br>
----- Method: ThreadedFFIPlugin class>>preambleCCode (in category 'translation') -----<br>
preambleCCode<br>
"For a source of builtin defines grep for builtin_define in a gcc release config directory.<br>
See See platforms/Cross/vm/sqCogStackAlignment.h for per-platform definitions for<br>
STACK_ALIGN_BYTES MUST_ALIGN_STACK et al."<br>
^'<br>
#include "sqAssert.h" /* for assert */<br>
#define ThreadedFFIPlugin 1 /* to filter-out unwanted declarations from sqFFI.h */<br>
#include "sqFFI.h" /* for logging and surface functions */<br>
#include "sqCogStackAlignment.h" /* for STACK_ALIGN_BYTES and getsp() */<br>
<br>
#ifdef _MSC_VER<br>
# define alloca _alloca<br>
#endif<br>
#if defined(__GNUC__) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__))<br>
# define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp))<br>
# elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64))<br>
# define setsp(sp) asm volatile ("movq %0,%%rsp" : : "m"(sp))<br>
+ # elif defined(__arm64__) || defined(__aarch64__) || defined(ARM64)<br>
+ /* <a href="https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm" rel="noreferrer" target="_blank">https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm</a><br>
+ * <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/index.html" rel="noreferrer" target="_blank">http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/index.html</a><br>
+ */<br>
+ # if __GNUC__<br>
+ # define getfp() ({ usqIntptr_t fp; \<br>
+ asm volatile ("mov x0, x29" : "=r"(x29) : ); \<br>
+ fp; })<br>
+ # define getsp() ({ usqIntptr_t sp; \<br>
+ asm volatile ("mov x0, sp" : "=r"(sp) : ); \<br>
+ sp; })<br>
+ # define setsp(sp) asm volatile ("ldr x16, %0 \n\t" "mov sp, x16" : : "m"(sp) )<br>
+ # endif<br>
# elif defined(__GNUC__) && (defined(__arm__))<br>
# define setsp(sp) asm volatile ("ldr %%sp, %0" : : "m"(sp))<br>
#endif<br>
#if !!defined(getsp)<br>
# define getsp() 0<br>
#endif <br>
#if !!defined(setsp)<br>
# define setsp(ignored) 0<br>
#endif <br>
<br>
#if !!defined(STACK_ALIGN_BYTES)<br>
# define STACK_ALIGN_BYTES 0<br>
#endif /* !!defined(STACK_ALIGN_BYTES) */<br>
<br>
/* For ABI that require stack alignment greater than natural word size */<br>
#define MUST_ALIGN_STACK (STACK_ALIGN_BYTES > sizeof(void*))<br>
<br>
#if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)<br>
/* Both Mac OS X x86 and Win32 x86 return structs of a power of two in size<br>
* less than or equal to eight bytes in length in registers. Linux never does so.<br>
*/<br>
# if __linux__<br>
# define WIN32_X86_STRUCT_RETURN 0<br>
# else<br>
# define WIN32_X86_STRUCT_RETURN 1<br>
# endif<br>
# if _WIN32<br>
# define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1<br>
# endif<br>
# elif defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64)<br>
# if _WIN32 | _WIN64<br>
# define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1<br>
# endif<br>
#endif /* defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) */<br>
<br>
#if !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL)<br>
# if defined(__MINGW32__) && !!defined(__clang__) && (__GNUC__ >= 3) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__))<br>
/*<br>
* cygwin -mno-cygwin (MinGW) gcc 3.4.x''s alloca is a library routine that answers<br>
* %esp + xx, so the outgoing stack is offset by one or more word if uncorrected.<br>
* Grab the actual stack pointer to correct.<br>
*/<br>
# define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 1<br>
# else<br>
# define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 0<br>
# endif<br>
#endif /* !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL) */<br>
<br>
#if !!defined(PLATFORM_API_USES_CALLEE_POPS_CONVENTION)<br>
# define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 0<br>
#endif<br>
<br>
/* This alignment stuff is a hack for integerAt:put:size:signed:/primitiveFFIIntegerAt[Put].<br>
* The assumption right now is that all processors support unaligned access. That only<br>
* holds true for x86, x86-64 & ARMv6 & later. But this keeps us going until we can address<br>
* it properly.<br>
*/<br>
#define unalignedShortAt(a) shortAt(a)<br>
#define unalignedShortAtput(a,v) shortAtput(a,v)<br>
#define unalignedLong32At(a) long32At(a)<br>
#define unalignedLong32Atput(a,v) long32Atput(a,v)<br>
#define unalignedLong64At(a) long64At(a)<br>
#define unalignedLong64Atput(a,v) long64Atput(a,v)<br>
<br>
/* The dispatchOn:in:with:with: generates an unwanted call on error. Just squash it. */<br>
#define error(foo) 0<br>
#ifndef SQUEAK_BUILTIN_PLUGIN<br>
/* but print assert failures. */<br>
void<br>
warning(char *s) { /* Print an error message but don''t exit. */<br>
printf("\n%s\n", s);<br>
}<br>
#endif<br>
<br>
/* sanitize */<br>
#ifdef SQUEAK_BUILTIN_PLUGIN<br>
# define EXTERN <br>
#else<br>
# define EXTERN extern<br>
#endif<br>
'!<br>
<br>
Item was changed:<br>
----- Method: VMMaker class>>generateVMPlugins (in category 'configurations') -----<br>
generateVMPlugins<br>
^VMMaker<br>
generatePluginsTo: self sourceTree, '/src'<br>
options: #()<br>
platformDir: self sourceTree, '/platforms'<br>
including:#( ADPCMCodecPlugin AsynchFilePlugin<br>
BalloonEnginePlugin B3DAcceleratorPlugin B3DEnginePlugin BMPReadWriterPlugin BitBltSimulation<br>
BochsIA32Plugin BochsX64Plugin<br>
CameraPlugin CroquetPlugin DeflatePlugin DropPlugin<br>
"Cryptography Plugins:" DESPlugin DSAPlugin MD5Plugin SHA256Plugin<br>
"FT2Plugin" FFTPlugin FileCopyPlugin FilePlugin FileAttributesPlugin FloatArrayPlugin FloatMathPlugin<br>
GeniePlugin GdbARMPlugin HostWindowPlugin IA32ABIPlugin ImmX11Plugin InternetConfigPlugin<br>
JPEGReadWriter2Plugin JPEGReaderPlugin JoystickTabletPlugin KlattSynthesizerPlugin<br>
LargeIntegersPlugin LocalePlugin MIDIPlugin MacMenubarPlugin Matrix2x3Plugin<br>
MiscPrimitivePlugin Mpeg3Plugin QuicktimePlugin RePlugin<br>
ScratchPlugin SecurityPlugin SerialPlugin SocketPlugin<br>
SoundCodecPlugin SoundGenerationPlugin SoundPlugin SqueakSSLPlugin StarSqueakPlugin<br>
+ ThreadedFFIPlugin ThreadedARMFFIPlugin ThreadedARM64FFIPlugin ThreadedIA32FFIPlugin<br>
+ ThreadedX64SysVFFIPlugin ThreadedX64Win64FFIPlugin<br>
- ThreadedFFIPlugin ThreadedARMFFIPlugin ThreadedIA32FFIPlugin ThreadedX64SysVFFIPlugin ThreadedX64Win64FFIPlugin<br>
UnicodePlugin UnixAioPlugin UUIDPlugin UnixOSProcessPlugin<br>
Win32OSProcessPlugin VMProfileLinuxSupportPlugin VMProfileMacSupportPlugin WeDoPlugin<br>
XDisplayControlPlugin)!<br>
<br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>