xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp

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

     1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /* Implement shared vtbl methods. */
     8 #include "xptcprivate.h"
     9 #include "xptiprivate.h"
    11 #ifndef WIN32
    12 #error "This code is for Win32 only"
    13 #endif
    15 extern "C" {
    17 #ifndef __GNUC__
    18 static
    19 #endif
    20 nsresult __stdcall
    21 PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
    22                    uint32_t* args, uint32_t* stackBytesToPop)
    23 {
    24 #define PARAM_BUFFER_COUNT     16
    26     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
    27     nsXPTCMiniVariant* dispatchParams = nullptr;
    28     const nsXPTMethodInfo* info = nullptr;
    29     uint8_t paramCount;
    30     uint8_t i;
    31     nsresult result = NS_ERROR_FAILURE;
    33     // If anything fails before stackBytesToPop can be set then
    34     // the failure is completely catastrophic!
    36     NS_ASSERTION(self,"no self");
    38     self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
    39     NS_ASSERTION(info,"no method info");
    41     paramCount = info->GetParamCount();
    43     // setup variant array pointer
    44     if(paramCount > PARAM_BUFFER_COUNT)
    45         dispatchParams = new nsXPTCMiniVariant[paramCount];
    46     else
    47         dispatchParams = paramBuffer;
    48     NS_ASSERTION(dispatchParams,"no place for params");
    50     uint32_t* ap = args;
    51     for(i = 0; i < paramCount; i++, ap++)
    52     {
    53         const nsXPTParamInfo& param = info->GetParam(i);
    54         const nsXPTType& type = param.GetType();
    55         nsXPTCMiniVariant* dp = &dispatchParams[i];
    57         if(param.IsOut() || !type.IsArithmetic())
    58         {
    59             dp->val.p = (void*) *ap;
    60             continue;
    61         }
    62         // else
    63         switch(type)
    64         {
    65         case nsXPTType::T_I8     : dp->val.i8  = *((int8_t*)  ap);       break;
    66         case nsXPTType::T_I16    : dp->val.i16 = *((int16_t*) ap);       break;
    67         case nsXPTType::T_I32    : dp->val.i32 = *((int32_t*) ap);       break;
    68         case nsXPTType::T_I64    : dp->val.i64 = *((int64_t*) ap); ap++; break;
    69         case nsXPTType::T_U8     : dp->val.u8  = *((uint8_t*) ap);       break;
    70         case nsXPTType::T_U16    : dp->val.u16 = *((uint16_t*)ap);       break;
    71         case nsXPTType::T_U32    : dp->val.u32 = *((uint32_t*)ap);       break;
    72         case nsXPTType::T_U64    : dp->val.u64 = *((uint64_t*)ap); ap++; break;
    73         case nsXPTType::T_FLOAT  : dp->val.f   = *((float*)   ap);       break;
    74         case nsXPTType::T_DOUBLE : dp->val.d   = *((double*)  ap); ap++; break;
    75         case nsXPTType::T_BOOL   : dp->val.b   = *((bool*)  ap);       break;
    76         case nsXPTType::T_CHAR   : dp->val.c   = *((char*)    ap);       break;
    77         case nsXPTType::T_WCHAR  : dp->val.wc  = *((wchar_t*) ap);       break;
    78         default:
    79             NS_ERROR("bad type");
    80             break;
    81         }
    82     }
    83     *stackBytesToPop = ((uint32_t)ap) - ((uint32_t)args);
    85     result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
    87     if(dispatchParams != paramBuffer)
    88         delete [] dispatchParams;
    90     return result;
    91 }
    93 } // extern "C"
    95 // declspec(naked) is broken in gcc
    96 #ifndef __GNUC__
    97 static 
    98 __declspec(naked)
    99 void SharedStub(void)
   100 {
   101     __asm {
   102         push ebp            // set up simple stack frame
   103         mov  ebp, esp       // stack has: ebp/vtbl_index/retaddr/this/args
   104         push ecx            // make room for a ptr
   105         lea  eax, [ebp-4]   // pointer to stackBytesToPop
   106         push eax
   107         lea  eax, [ebp+12]  // pointer to args
   108         push eax
   109         push ecx            // vtbl_index
   110         mov  eax, [ebp+8]   // this
   111         push eax
   112         call PrepareAndDispatch
   113         mov  edx, [ebp+4]   // return address
   114         mov  ecx, [ebp-4]   // stackBytesToPop
   115         add  ecx, 8         // for 'this' and return address
   116         mov  esp, ebp
   117         pop  ebp
   118         add  esp, ecx       // fix up stack pointer
   119         jmp  edx            // simulate __stdcall return
   120     }
   121 }
   123 // these macros get expanded (many times) in the file #included below
   124 #define STUB_ENTRY(n) \
   125 __declspec(naked) nsresult __stdcall nsXPTCStubBase::Stub##n() \
   126 { __asm mov ecx, n __asm jmp SharedStub }
   128 #else
   130 asm(".text\n\t"
   131     ".align     4\n\t"
   132     "SharedStub:\n\t"
   133     "push       %ebp\n\t"
   134     "mov        %esp, %ebp\n\t"
   135     "push       %ecx\n\t"
   136     "lea        -4(%ebp), %eax\n\t"
   137     "push       %eax\n\t"
   138     "lea        12(%ebp), %eax\n\t"
   139     "push       %eax\n\t"
   140     "push       %ecx\n\t"
   141     "movl       8(%ebp), %eax\n\t"
   142     "push       %eax\n\t"
   143     "call       _PrepareAndDispatch@16\n\t"
   144     "mov        4(%ebp), %edx\n\t"
   145     "mov        -4(%ebp), %ecx\n\t"
   146     "add        $8, %ecx\n\t"
   147     "mov        %ebp, %esp\n\t"
   148     "pop        %ebp\n\t"
   149     "add        %ecx, %esp\n\t"
   150     "jmp        *%edx"
   151 );
   153 #define STUB_ENTRY(n) \
   154 asm(".text\n\t" \
   155     ".align     4\n\t" \
   156     ".if	" #n " < 10\n\t" \
   157     ".globl     __ZN14nsXPTCStubBase5Stub" #n "Ev@4\n\t" \
   158     ".def       __ZN14nsXPTCStubBase5Stub" #n "Ev@4; \n\t" \
   159     ".scl       3\n\t" \
   160     ".type      46\n\t" \
   161     ".endef\n\t" \
   162     "__ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n\t" \
   163     ".elseif	" #n " < 100\n\t" \
   164     ".globl     __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \
   165     ".def       __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \
   166     ".scl       3\n\t" \
   167     ".type      46\n\t" \
   168     ".endef\n\t" \
   169     "__ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n\t" \
   170     ".elseif    " #n " < 1000\n\t" \
   171     ".globl     __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \
   172     ".def       __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \
   173     ".scl       3\n\t" \
   174     ".type      46\n\t" \
   175     ".endef\n\t" \
   176     "__ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n\t" \
   177     ".else\n\t" \
   178     ".err	\"stub number " #n " >= 1000 not yet supported\"\n\t" \
   179     ".endif\n\t" \
   180     "mov $" #n ", %ecx\n\t" \
   181     "jmp SharedStub");
   183 #endif /* __GNUC__ */
   185 #define SENTINEL_ENTRY(n) \
   186 nsresult __stdcall nsXPTCStubBase::Sentinel##n() \
   187 { \
   188     NS_ERROR("nsXPTCStubBase::Sentinel called"); \
   189     return NS_ERROR_NOT_IMPLEMENTED; \
   190 }
   192 #ifdef _MSC_VER
   193 #pragma warning(disable : 4035) // OK to have no return value
   194 #endif
   195 #include "xptcstubsdef.inc"
   196 #ifdef _MSC_VER
   197 #pragma warning(default : 4035) // restore default
   198 #endif
   200 void
   201 #ifdef __GNUC__
   202 __cdecl
   203 #endif
   204 xptc_dummy()
   205 {
   206 }

mercurial