1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,206 @@ 1.4 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* Implement shared vtbl methods. */ 1.10 + 1.11 +#include "xptcprivate.h" 1.12 +#include "xptiprivate.h" 1.13 + 1.14 +#ifndef WIN32 1.15 +#error "This code is for Win32 only" 1.16 +#endif 1.17 + 1.18 +extern "C" { 1.19 + 1.20 +#ifndef __GNUC__ 1.21 +static 1.22 +#endif 1.23 +nsresult __stdcall 1.24 +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, 1.25 + uint32_t* args, uint32_t* stackBytesToPop) 1.26 +{ 1.27 +#define PARAM_BUFFER_COUNT 16 1.28 + 1.29 + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; 1.30 + nsXPTCMiniVariant* dispatchParams = nullptr; 1.31 + const nsXPTMethodInfo* info = nullptr; 1.32 + uint8_t paramCount; 1.33 + uint8_t i; 1.34 + nsresult result = NS_ERROR_FAILURE; 1.35 + 1.36 + // If anything fails before stackBytesToPop can be set then 1.37 + // the failure is completely catastrophic! 1.38 + 1.39 + NS_ASSERTION(self,"no self"); 1.40 + 1.41 + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); 1.42 + NS_ASSERTION(info,"no method info"); 1.43 + 1.44 + paramCount = info->GetParamCount(); 1.45 + 1.46 + // setup variant array pointer 1.47 + if(paramCount > PARAM_BUFFER_COUNT) 1.48 + dispatchParams = new nsXPTCMiniVariant[paramCount]; 1.49 + else 1.50 + dispatchParams = paramBuffer; 1.51 + NS_ASSERTION(dispatchParams,"no place for params"); 1.52 + 1.53 + uint32_t* ap = args; 1.54 + for(i = 0; i < paramCount; i++, ap++) 1.55 + { 1.56 + const nsXPTParamInfo& param = info->GetParam(i); 1.57 + const nsXPTType& type = param.GetType(); 1.58 + nsXPTCMiniVariant* dp = &dispatchParams[i]; 1.59 + 1.60 + if(param.IsOut() || !type.IsArithmetic()) 1.61 + { 1.62 + dp->val.p = (void*) *ap; 1.63 + continue; 1.64 + } 1.65 + // else 1.66 + switch(type) 1.67 + { 1.68 + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; 1.69 + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; 1.70 + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; 1.71 + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; 1.72 + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; 1.73 + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; 1.74 + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; 1.75 + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; 1.76 + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; 1.77 + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; 1.78 + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; 1.79 + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; 1.80 + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; 1.81 + default: 1.82 + NS_ERROR("bad type"); 1.83 + break; 1.84 + } 1.85 + } 1.86 + *stackBytesToPop = ((uint32_t)ap) - ((uint32_t)args); 1.87 + 1.88 + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); 1.89 + 1.90 + if(dispatchParams != paramBuffer) 1.91 + delete [] dispatchParams; 1.92 + 1.93 + return result; 1.94 +} 1.95 + 1.96 +} // extern "C" 1.97 + 1.98 +// declspec(naked) is broken in gcc 1.99 +#ifndef __GNUC__ 1.100 +static 1.101 +__declspec(naked) 1.102 +void SharedStub(void) 1.103 +{ 1.104 + __asm { 1.105 + push ebp // set up simple stack frame 1.106 + mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args 1.107 + push ecx // make room for a ptr 1.108 + lea eax, [ebp-4] // pointer to stackBytesToPop 1.109 + push eax 1.110 + lea eax, [ebp+12] // pointer to args 1.111 + push eax 1.112 + push ecx // vtbl_index 1.113 + mov eax, [ebp+8] // this 1.114 + push eax 1.115 + call PrepareAndDispatch 1.116 + mov edx, [ebp+4] // return address 1.117 + mov ecx, [ebp-4] // stackBytesToPop 1.118 + add ecx, 8 // for 'this' and return address 1.119 + mov esp, ebp 1.120 + pop ebp 1.121 + add esp, ecx // fix up stack pointer 1.122 + jmp edx // simulate __stdcall return 1.123 + } 1.124 +} 1.125 + 1.126 +// these macros get expanded (many times) in the file #included below 1.127 +#define STUB_ENTRY(n) \ 1.128 +__declspec(naked) nsresult __stdcall nsXPTCStubBase::Stub##n() \ 1.129 +{ __asm mov ecx, n __asm jmp SharedStub } 1.130 + 1.131 +#else 1.132 + 1.133 +asm(".text\n\t" 1.134 + ".align 4\n\t" 1.135 + "SharedStub:\n\t" 1.136 + "push %ebp\n\t" 1.137 + "mov %esp, %ebp\n\t" 1.138 + "push %ecx\n\t" 1.139 + "lea -4(%ebp), %eax\n\t" 1.140 + "push %eax\n\t" 1.141 + "lea 12(%ebp), %eax\n\t" 1.142 + "push %eax\n\t" 1.143 + "push %ecx\n\t" 1.144 + "movl 8(%ebp), %eax\n\t" 1.145 + "push %eax\n\t" 1.146 + "call _PrepareAndDispatch@16\n\t" 1.147 + "mov 4(%ebp), %edx\n\t" 1.148 + "mov -4(%ebp), %ecx\n\t" 1.149 + "add $8, %ecx\n\t" 1.150 + "mov %ebp, %esp\n\t" 1.151 + "pop %ebp\n\t" 1.152 + "add %ecx, %esp\n\t" 1.153 + "jmp *%edx" 1.154 +); 1.155 + 1.156 +#define STUB_ENTRY(n) \ 1.157 +asm(".text\n\t" \ 1.158 + ".align 4\n\t" \ 1.159 + ".if " #n " < 10\n\t" \ 1.160 + ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev@4\n\t" \ 1.161 + ".def __ZN14nsXPTCStubBase5Stub" #n "Ev@4; \n\t" \ 1.162 + ".scl 3\n\t" \ 1.163 + ".type 46\n\t" \ 1.164 + ".endef\n\t" \ 1.165 + "__ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n\t" \ 1.166 + ".elseif " #n " < 100\n\t" \ 1.167 + ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \ 1.168 + ".def __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \ 1.169 + ".scl 3\n\t" \ 1.170 + ".type 46\n\t" \ 1.171 + ".endef\n\t" \ 1.172 + "__ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n\t" \ 1.173 + ".elseif " #n " < 1000\n\t" \ 1.174 + ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \ 1.175 + ".def __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \ 1.176 + ".scl 3\n\t" \ 1.177 + ".type 46\n\t" \ 1.178 + ".endef\n\t" \ 1.179 + "__ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n\t" \ 1.180 + ".else\n\t" \ 1.181 + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ 1.182 + ".endif\n\t" \ 1.183 + "mov $" #n ", %ecx\n\t" \ 1.184 + "jmp SharedStub"); 1.185 + 1.186 +#endif /* __GNUC__ */ 1.187 + 1.188 +#define SENTINEL_ENTRY(n) \ 1.189 +nsresult __stdcall nsXPTCStubBase::Sentinel##n() \ 1.190 +{ \ 1.191 + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ 1.192 + return NS_ERROR_NOT_IMPLEMENTED; \ 1.193 +} 1.194 + 1.195 +#ifdef _MSC_VER 1.196 +#pragma warning(disable : 4035) // OK to have no return value 1.197 +#endif 1.198 +#include "xptcstubsdef.inc" 1.199 +#ifdef _MSC_VER 1.200 +#pragma warning(default : 4035) // restore default 1.201 +#endif 1.202 + 1.203 +void 1.204 +#ifdef __GNUC__ 1.205 +__cdecl 1.206 +#endif 1.207 +xptc_dummy() 1.208 +{ 1.209 +}