diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /xpcom/reflect | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'xpcom/reflect')
157 files changed, 20969 insertions, 0 deletions
diff --git a/xpcom/reflect/moz.build b/xpcom/reflect/moz.build new file mode 100644 index 000000000..c04892d00 --- /dev/null +++ b/xpcom/reflect/moz.build @@ -0,0 +1,8 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += ['xptinfo', 'xptcall'] + diff --git a/xpcom/reflect/xptcall/README b/xpcom/reflect/xptcall/README new file mode 100644 index 000000000..0c401fe88 --- /dev/null +++ b/xpcom/reflect/xptcall/README @@ -0,0 +1,6 @@ +see: + +http://www.mozilla.org/scriptable/xptcall-faq.html +and +http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html + diff --git a/xpcom/reflect/xptcall/genstubs.pl b/xpcom/reflect/xptcall/genstubs.pl new file mode 100644 index 000000000..16ae2006a --- /dev/null +++ b/xpcom/reflect/xptcall/genstubs.pl @@ -0,0 +1,88 @@ +#!/usr/local/bin/perl +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +# This is used to generate stub entry points. We generate a file to +# be included in the declaraion and a file to be used for expanding macros +# to represent the implementation of the stubs. + +# +# if "$entry_count" is ever changed and the .inc files regenerated then +# the following issues need to be addressed: +# +# 1) The current Linux ARM code has a limitation of only having 256-3 stubs, +# as a result of the limitations of immediate values in ARM assembly. +# +# This number is verified by the IDL parser in xpcom/idl-parser/xpidl.py, as +# well as in xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp, to +# prevent generating interfaces or loading xpt files that would cause the +# stubs to run off the entries. +# If you change this number, please update that location. + +# 3 entries are already 'used' by the 3 methods of nsISupports. +# 3+247+5=255 This should get us in under the Linux ARM limitation +$entry_count = 247; +$sentinel_count = 5; + +$decl_name = "xptcstubsdecl.inc"; +$def_name = "xptcstubsdef.inc"; + +## +## Write the declarations include file +## + +die "Can't open $decl_name" if !open(OUTFILE, ">$decl_name"); + +print OUTFILE "/* generated file - DO NOT EDIT */\n\n"; +print OUTFILE "/* includes ",$entry_count," stub entries, and ", + $sentinel_count," sentinel entries */\n\n"; +print OUTFILE "/*\n"; +print OUTFILE "* declarations of normal stubs...\n"; +print OUTFILE "* 0 is QueryInterface\n"; +print OUTFILE "* 1 is AddRef\n"; +print OUTFILE "* 2 is Release\n"; +print OUTFILE "*/\n"; +print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))\n"; +for($i = 0; $i < $entry_count; $i++) { + print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n"; +} +print OUTFILE "#else\n"; +for($i = 0; $i < $entry_count; $i++) { + print OUTFILE "NS_IMETHOD Stub",$i+3,"(uint64_t,uint64_t,\n"; + print OUTFILE " uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);\n"; + +} +print OUTFILE "#endif\n"; + +print OUTFILE "\n/* declarations of sentinel stubs */\n"; + +for($i = 0; $i < $sentinel_count; $i++) { + print OUTFILE "NS_IMETHOD Sentinel",$i,"();\n"; +} +close(OUTFILE); + + +## +## Write the definitions include file. This assumes a macro will be used to +## expand the entries written... +## + +die "Can't open $def_name" if !open(OUTFILE, ">$def_name"); + +## Disabled for bug 275004 - followup to fix is Bug 419604 +my $warn_inc_is_generated = 0; +if ($warn_inc_is_generated) { +print OUTFILE "/* generated file - DO NOT EDIT */\n\n"; +print OUTFILE "/* includes ",$entry_count," stub entries, and ", + $sentinel_count," sentinel entries */\n\n"; +} + +for($i = 0; $i < $entry_count; $i++) { + print OUTFILE "STUB_ENTRY(",$i+3,")\n"; +} + +for($i = 0; $i < $sentinel_count; $i++) { + print OUTFILE "SENTINEL_ENTRY(",$i,")\n"; +} diff --git a/xpcom/reflect/xptcall/md/moz.build b/xpcom/reflect/xptcall/md/moz.build new file mode 100644 index 000000000..a4b59aaf0 --- /dev/null +++ b/xpcom/reflect/xptcall/md/moz.build @@ -0,0 +1,12 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +arch = CONFIG['OS_ARCH'] + +if arch == 'WINNT': + DIRS += ['win32'] +else: + DIRS += ['unix'] diff --git a/xpcom/reflect/xptcall/md/test/README b/xpcom/reflect/xptcall/md/test/README new file mode 100644 index 000000000..04850b2e0 --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/README @@ -0,0 +1,6 @@ +These are just simple test programs in which stripped down versions of the +XPConnect invoke and stubs code can be built and tested as the code is brought +up on various platforms. These probrams do not test the param sizing and copying +functionality of the routines. However, they do supply a place where the lowest +level assembly language code can be developed and debugged in the simplest of +contexts before it is moved into the real routines.
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/clean.bat b/xpcom/reflect/xptcall/md/test/clean.bat new file mode 100755 index 000000000..f320e222c --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/clean.bat @@ -0,0 +1,5 @@ +@echo off +echo deleting intermediate files +if exist *.obj del *.obj > NUL +if exist *.ilk del *.ilk > NUL +if exist *.pdb del *.pdb > NUL
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/invoke_test.cpp b/xpcom/reflect/xptcall/md/test/invoke_test.cpp new file mode 100644 index 000000000..068db8b2f --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/invoke_test.cpp @@ -0,0 +1,207 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdio.h> + +typedef unsigned nsresult; +typedef unsigned uint32_t; +typedef unsigned nsXPCVariant; + + +#if defined(WIN32) +#define NS_IMETHOD virtual nsresult __stdcall +#define NS_IMETHODIMP nsresult __stdcall +#else +#define NS_IMETHOD virtual nsresult +#define NS_IMETHODIMP nsresult +#endif + + +class base{ +public: + NS_IMETHOD ignored() = 0; +}; + +class foo : public base { +public: + NS_IMETHOD callme1(int i, int j) = 0; + NS_IMETHOD callme2(int i, int j) = 0; + NS_IMETHOD callme3(int i, int j) = 0; +}; + +class bar : public foo{ +public: + NS_IMETHOD ignored(); + NS_IMETHOD callme1(int i, int j); + NS_IMETHOD callme2(int i, int j); + NS_IMETHOD callme3(int i, int j); +}; + +/* +class baz : public base { +public: + NS_IMETHOD ignored(); + NS_IMETHOD callme1(); + NS_IMETHOD callme2(); + NS_IMETHOD callme3(); + void setfoo(foo* f) {other = f;} + + foo* other; +}; +NS_IMETHODIMP baz::ignored(){return 0;} +*/ + +NS_IMETHODIMP bar::ignored(){return 0;} + +NS_IMETHODIMP bar::callme1(int i, int j) +{ + printf("called bar::callme1 with: %d %d\n", i, j); + return 5; +} + +NS_IMETHODIMP bar::callme2(int i, int j) +{ + printf("called bar::callme2 with: %d %d\n", i, j); + return 5; +} + +NS_IMETHODIMP bar::callme3(int i, int j) +{ + printf("called bar::callme3 with: %d %d\n", i, j); + return 5; +} + +void docall(foo* f, int i, int j){ + f->callme1(i, j); +} + +/***************************************************************************/ +#if defined(WIN32) + +static uint32_t __stdcall +invoke_count_words(uint32_t paramCount, nsXPCVariant* s) +{ + return paramCount; +} + +static void __stdcall +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s) +{ + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + *((uint32_t*)d) = *((uint32_t*)s); + } +} + +static nsresult __stdcall +DoInvoke(void* that, uint32_t index, + uint32_t paramCount, nsXPCVariant* params) +{ + __asm { + push params + push paramCount + call invoke_count_words // stdcall, result in eax + shl eax,2 // *= 4 + sub esp,eax // make space for params + mov edx,esp + push params + push paramCount + push edx + call invoke_copy_to_stack // stdcall + mov ecx,that // instance in ecx + push ecx // push this + mov edx,[ecx] // vtable in edx + mov eax,index + shl eax,2 // *= 4 + add edx,eax + call [edx] // stdcall, i.e. callee cleans up stack. + } +} + +#else +/***************************************************************************/ +// just Linux_x86 now. Add other later... + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPCVariant* s) +{ + return paramCount; +} + +static void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s) +{ + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + *((uint32_t*)d) = *((uint32_t*)s); + } +} + +static nsresult +DoInvoke(void* that, uint32_t index, + uint32_t paramCount, nsXPCVariant* params) +{ + uint32_t result; + void* fn_count = invoke_count_words; + void* fn_copy = invoke_copy_to_stack; + + __asm__ __volatile__( + "pushl %4\n\t" + "pushl %3\n\t" + "movl %5, %%eax\n\t" + "call *%%eax\n\t" /* count words */ + "addl $0x8, %%esp\n\t" + "shl $2, %%eax\n\t" /* *= 4 */ + "subl %%eax, %%esp\n\t" /* make room for params */ + "movl %%esp, %%edx\n\t" + "pushl %4\n\t" + "pushl %3\n\t" + "pushl %%edx\n\t" + "movl %6, %%eax\n\t" + "call *%%eax\n\t" /* copy params */ + "addl $0xc, %%esp\n\t" + "movl %1, %%ecx\n\t" + "pushl %%ecx\n\t" + "movl (%%ecx), %%edx\n\t" + "movl %2, %%eax\n\t" /* function index */ + "shl $2, %%eax\n\t" /* *= 4 */ + "addl $8, %%eax\n\t" /* += 8 */ + "addl %%eax, %%edx\n\t" + "call *(%%edx)\n\t" /* safe to not cleanup esp */ + "movl %%eax, %0" + : "=g" (result) /* %0 */ + : "g" (that), /* %1 */ + "g" (index), /* %2 */ + "g" (paramCount), /* %3 */ + "g" (params), /* %4 */ + "g" (fn_count), /* %5 */ + "g" (fn_copy) /* %6 */ + : "ax", "cx", "dx", "memory" + ); + + return result; +} + +#endif +/***************************************************************************/ + +int main() +{ + nsXPCVariant params1[2] = {1,2}; + nsXPCVariant params2[2] = {2,4}; + nsXPCVariant params3[2] = {3,6}; + + foo* a = new bar(); + +// printf("calling via C++...\n"); +// docall(a, 12, 24); + + printf("calling via ASM...\n"); + DoInvoke(a, 1, 2, params1); + DoInvoke(a, 2, 2, params2); + DoInvoke(a, 3, 2, params3); + + return 0; +} diff --git a/xpcom/reflect/xptcall/md/test/mk_invoke.bat b/xpcom/reflect/xptcall/md/test/mk_invoke.bat new file mode 100755 index 000000000..10a9be51d --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/mk_invoke.bat @@ -0,0 +1,9 @@ +@echo off +@echo deleing old output +if exist invoke_test.obj del invoke_test.obj > NUL +if exist invoke_test.ilk del invoke_test.ilk > NUL +if exist *.pdb del *.pdb > NUL +if exist invoke_test.exe del invoke_test.exe > NUL + +@echo building... +cl /nologo -Zi -DWIN32 invoke_test.cpp
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/mk_stub.bat b/xpcom/reflect/xptcall/md/test/mk_stub.bat new file mode 100755 index 000000000..f9af17aff --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/mk_stub.bat @@ -0,0 +1,9 @@ +@echo off +@echo deleing old output +if exist stub_test.obj del stub_test.obj > NUL +if exist stub_test.ilk del stub_test.ilk > NUL +if exist *.pdb del *.pdb > NUL +if exist stub_test.exe del stub_test.exe > NUL + +@echo building... +cl /nologo -Zi -DWIN32 stub_test.cpp
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/moz.build b/xpcom/reflect/xptcall/md/test/moz.build new file mode 100644 index 000000000..2261c3ce6 --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +SimplePrograms([ + 'stub_test', +]) diff --git a/xpcom/reflect/xptcall/md/test/stub_test.cpp b/xpcom/reflect/xptcall/md/test/stub_test.cpp new file mode 100644 index 000000000..6c9559c65 --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/stub_test.cpp @@ -0,0 +1,213 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdio.h> + +typedef unsigned nsresult; +typedef unsigned uint32_t; +typedef unsigned nsXPCVariant; + + +#if defined(WIN32) +#define NS_IMETHOD virtual nsresult __stdcall +#define NS_IMETHODIMP nsresult __stdcall +#else +#define NS_IMETHOD virtual nsresult +#define NS_IMETHODIMP nsresult +#endif + + +class base{ +public: + NS_IMETHOD ignored() = 0; +}; + +class foo : public base { +public: + NS_IMETHOD callme1(int i, int j) = 0; + NS_IMETHOD callme2(int i, int j) = 0; + NS_IMETHOD callme3(int i, int j) = 0; +}; + +class bar : public foo{ +public: + NS_IMETHOD ignored(); + NS_IMETHOD callme1(int i, int j); + NS_IMETHOD callme2(int i, int j); + NS_IMETHOD callme3(int i, int j); +}; + +class baz : public base { +public: + NS_IMETHOD ignored(); + NS_IMETHOD callme1(); + NS_IMETHOD callme2(); + NS_IMETHOD callme3(); + void setfoo(foo* f) {other = f;} + + foo* other; +}; +NS_IMETHODIMP baz::ignored(){return 0;} + +NS_IMETHODIMP bar::ignored(){return 0;} + +NS_IMETHODIMP bar::callme1(int i, int j) +{ + printf("called bar::callme1 with: %d %d\n", i, j); + return 15; +} + +NS_IMETHODIMP bar::callme2(int i, int j) +{ + printf("called bar::callme2 with: %d %d\n", i, j); + return 25; +} + +NS_IMETHODIMP bar::callme3(int i, int j) +{ + printf("called bar::callme3 with: %d %d\n", i, j); + return 35; +} + +void docall(foo* f, int i, int j){ + f->callme1(i, j); +} + +/***************************************************************************/ +#if defined(WIN32) + +static int __stdcall +PrepareAndDispatch(baz* self, uint32_t methodIndex, + uint32_t* args, uint32_t* stackBytesToPop) +{ + fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n", + (void*)self, methodIndex, (void*)args); + foo* a = self->other; + int p1 = (int) *args; + int p2 = (int) *(args+1); + int out = 0; + switch(methodIndex) + { + case 1: out = a->callme1(p1, p2); break; + case 2: out = a->callme2(p1, p2); break; + case 3: out = a->callme3(p1, p2); break; + } + *stackBytesToPop = 2*4; + return out; +} + +#ifndef __GNUC__ +static __declspec(naked) void SharedStub(void) +{ + __asm { + push ebp // set up simple stack frame + mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args + push ecx // make room for a ptr + lea eax, [ebp-4] // pointer to stackBytesToPop + push eax + lea ecx, [ebp+16] // pointer to args + push ecx + mov edx, [ebp+4] // vtbl_index + push edx + mov eax, [ebp+12] // this + push eax + call PrepareAndDispatch + mov edx, [ebp+8] // return address + mov ecx, [ebp-4] // stackBytesToPop + add ecx, 12 // for this, the index, and ret address + mov esp, ebp + pop ebp + add esp, ecx // fix up stack pointer + jmp edx // simulate __stdcall return + } +} + +// these macros get expanded (many times) in the file #included below +#define STUB_ENTRY(n) \ +__declspec(naked) nsresult __stdcall baz::callme##n() \ +{ __asm push n __asm jmp SharedStub } + +#else /* __GNUC__ */ + +#define STUB_ENTRY(n) \ +nsresult __stdcall baz::callme##n() \ +{ \ + uint32_t *args, stackBytesToPop; \ + int result = 0; \ + baz *obj; \ + __asm__ __volatile__ ( \ + "leal 0x0c(%%ebp), %0\n\t" /* args */ \ + "movl 0x08(%%ebp), %1\n\t" /* this */ \ + : "=r" (args), \ + "=r" (obj)); \ + result = PrepareAndDispatch(obj, n, args,&stackBytesToPop); \ + fprintf(stdout, "stub returning: %d\n", result); \ + fprintf(stdout, "bytes to pop: %d\n", stackBytesToPop); \ + return result; \ +} + +#endif /* ! __GNUC__ */ + +#else +/***************************************************************************/ +// just Linux_x86 now. Add other later... + +static int +PrepareAndDispatch(baz* self, uint32_t methodIndex, uint32_t* args) +{ + foo* a = self->other; + int p1 = (int) *args; + int p2 = (int) *(args+1); + switch(methodIndex) + { + case 1: a->callme1(p1, p2); break; + case 2: a->callme2(p1, p2); break; + case 3: a->callme3(p1, p2); break; + } + return 1; +} + +#define STUB_ENTRY(n) \ +nsresult baz::callme##n() \ +{ \ + void* method = PrepareAndDispatch; \ + nsresult result; \ + __asm__ __volatile__( \ + "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \ + "pushl %%ecx\n\t" \ + "pushl $"#n"\n\t" /* method index */ \ + "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \ + "pushl %%ecx\n\t" \ + "call *%%edx" /* PrepareAndDispatch */ \ + : "=a" (result) /* %0 */ \ + : "d" (method) /* %1 */ \ + : "memory" ); \ + return result; \ +} + +#endif +/***************************************************************************/ + +STUB_ENTRY(1) +STUB_ENTRY(2) +STUB_ENTRY(3) + +int main() +{ + foo* a = new bar(); + baz* b = new baz(); + + /* here we make the global 'check for alloc failure' checker happy */ + if(!a || !b) + return 1; + + foo* c = (foo*)b; + + b->setfoo(a); + c->callme1(1,2); + c->callme2(2,4); + c->callme3(3,6); + + return 0; +} diff --git a/xpcom/reflect/xptcall/md/unix/Makefile.in b/xpcom/reflect/xptcall/md/unix/Makefile.in new file mode 100644 index 000000000..e4cdc389b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/Makefile.in @@ -0,0 +1,79 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +###################################################################### +# HPPA +###################################################################### +# +# HP-UX/PA32 +# +# for gas and gcc, check comment in xptcinvoke_asm_pa32.s +ifeq ($(OS_ARCH),HP-UX) +ifneq ($(CC),gcc) +# #18875 Building the CPP's (CXX) optimized causes a crash +CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS)) +endif +endif + +# +# Linux/HPPA/gcc +# +ifeq ($(OS_ARCH),Linux) +ifneq (,$(filter hppa hppa2.0 hppa1.1,$(OS_TEST))) +ifndef GNU_CXX +else +# #434190 optimized builds crash +CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS)) +endif +endif +endif + + +###################################################################### +# PowerPC +###################################################################### +# +# AIX/PPC +# +ifeq ($(OS_ARCH),AIX) +# #24617 Building the CPP's (CXX) optimized causes a crash +CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS)) +endif + +include $(topsrcdir)/config/rules.mk + +ifeq ($(OS_ARCH),Linux) +ifneq (,$(findstring mips, $(OS_TEST))) +xptcstubs_asm_mips.o: $(DIST)/include/xptcstubsdef.inc +endif +endif + +ifeq ($(OS_ARCH),Darwin) +xptcstubs_asm_ppc_darwin.s: xptcstubs_asm_ppc_darwin.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile + gm4 $(INCLUDES) $< > $@ +endif + +ifeq ($(OS_ARCH),AIX) +ifdef HAVE_64BIT_BUILD +xptcstubs_asm_ppc_aix64.s: xptcstubs_asm_ppc_aix64.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile + m4 -DAIX_OBJMODEL=$(AIX_OBJMODEL) $(INCLUDES) -I. $< > $@ +else +xptcstubs_asm_ppc_aix.s: xptcstubs_asm_ppc_aix.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile + m4 -DAIX_OBJMODEL=$(AIX_OBJMODEL) $(INCLUDES) -I. $< > $@ +endif +endif + +ifeq ($(OS_ARCH),SunOS) +ifeq (86,$(findstring 86,$(OS_TEST))) +ifndef GNU_CC +xptcstubsdef_asm.solx86: $(DIST)/include/xptcstubsdef.inc + sed \ + -e 's/^\(STUB_ENTRY\)(\([0-9]\))/\11\(\2\)/' \ + -e 's/^\(STUB_ENTRY\)(\([0-9][0-9]\))/\12\(\2\)/' \ + -e 's/^\(STUB_ENTRY\)(\([0-9][0-9][0-9]\))/\13\(\2\)/' \ + $(DIST)/include/xptcstubsdef.inc > $@ +endif +endif +endif diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build new file mode 100644 index 000000000..1d182bbd6 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/moz.build @@ -0,0 +1,327 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG['OS_ARCH'] == 'Darwin': + SOURCES += [ + 'xptcinvoke_darwin.cpp', + 'xptcstubs_darwin.cpp', + ] + if CONFIG['OS_TEST'] == 'powerpc': + SOURCES += [ + '!xptcstubs_asm_ppc_darwin.s', + 'xptcinvoke_asm_ppc_rhapsody.s', + ] + if '86' in CONFIG['OS_TEST'] and CONFIG['OS_TEST'] != 'x86_64': + DEFINES['MOZ_NEED_LEADING_UNDERSCORE'] = True + +if CONFIG['OS_ARCH'] == 'GNU': + if CONFIG['CPU_ARCH'] == 'x86': + SOURCES += [ + 'xptcinvoke_gcc_x86_unix.cpp', + 'xptcstubs_gcc_x86_unix.cpp' + ] + +if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD') or \ + CONFIG['OS_ARCH'].startswith('GNU_'): + if CONFIG['OS_TEST'] == 'x86_64': + SOURCES += [ + 'xptcinvoke_x86_64_unix.cpp', + 'xptcstubs_x86_64_linux.cpp', + ] + elif '86' in CONFIG['OS_TEST']: + SOURCES += [ + 'xptcinvoke_gcc_x86_unix.cpp', + 'xptcstubs_gcc_x86_unix.cpp' + ] + +if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'): + if 'ia64' in CONFIG['OS_TEST']: + SOURCES += [ + 'xptcinvoke_asm_ipf64.s', + 'xptcinvoke_ipf64.cpp', + 'xptcstubs_asm_ipf64.s', + 'xptcstubs_ipf64.cpp' + ] + +if CONFIG['OS_ARCH'] == 'SunOS' and '86' in CONFIG['OS_TEST']: + GENERATED_FILES = [ + 'xptcstubsdef_asm.solx86', + ] + if CONFIG['OS_TEST'] == 'x86_64': + if CONFIG['GNU_CC']: + SOURCES += [ + 'xptcinvoke_x86_64_unix.cpp', + 'xptcstubs_x86_64_linux.cpp' + ] + else: + ASFLAGS += ['-xarch=amd64'] + SOURCES += [ + 'xptcinvoke_x86_64_solaris.cpp', + 'xptcstubs_asm_x86_64_solaris_SUNW.s', + 'xptcstubs_x86_64_solaris.cpp', + ] + else: + if CONFIG['GNU_CC']: + SOURCES += [ + 'xptcinvoke_gcc_x86_unix.cpp', + 'xptcstubs_gcc_x86_unix.cpp' + ] + else: + SOURCES += [ + 'xptcinvoke_asm_x86_solaris_SUNW.s', + 'xptcinvoke_x86_solaris.cpp', + 'xptcstubs_asm_x86_solaris_SUNW.s', + 'xptcstubs_x86_solaris.cpp' + ] + +if CONFIG['OS_TEST'] == 'alpha': + if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD'): + SOURCES += [ + 'xptcinvoke_linux_alpha.cpp', + 'xptcstubs_linux_alpha.cpp', + ] + elif CONFIG['OS_ARCH'] == 'OpenBSD': + SOURCES += [ + 'xptcinvoke_alpha_openbsd.cpp', + 'xptcstubs_alpha_openbsd.cpp', + ] + +if CONFIG['CPU_ARCH'] == 'arm' or CONFIG['OS_TEST'] == 'sa110': + if CONFIG['OS_ARCH'] == 'Linux': + SOURCES += [ + 'xptcinvoke_arm.cpp', + 'xptcstubs_arm.cpp' + ] + CXXFLAGS += ['-O2'] + elif CONFIG['OS_ARCH'] == 'NetBSD': + SOURCES += [ + 'xptcinvoke_arm_netbsd.cpp', + 'xptcstubs_arm_netbsd.cpp', + ] + +if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['OS_ARCH'] in ('Bitrig', 'OpenBSD'): + SOURCES += [ + 'xptcinvoke_arm_openbsd.cpp', + 'xptcstubs_arm_openbsd.cpp', + ] + +if CONFIG['OS_ARCH'] == 'HP-UX': + if CONFIG['CC'] != 'gcc': + if CONFIG['OS_TEST'] == 'ia64': + SOURCES += [ + 'xptcinvoke_asm_ipf32.s', + 'xptcinvoke_ipf32.cpp', + 'xptcstubs_asm_ipf32.s', + 'xptcstubs_ipf32.cpp', + ] + else: + SOURCES += [ + 'xptcinvoke_asm_pa32.s', + 'xptcinvoke_pa32.cpp', + 'xptcstubs_asm_pa32.s', + 'xptcstubs_pa32.cpp' + ] + +if CONFIG['OS_ARCH'] == 'Linux': + if CONFIG['OS_TEST'] in ('hppa', 'hppa2.0', 'hppa1.1'): + if CONFIG['GNU_CXX']: + SOURCES += [ + 'xptcinvoke_asm_parisc_linux.s', + 'xptcinvoke_pa32.cpp', + 'xptcstubs_asm_parisc_linux.s', + 'xptcstubs_pa32.cpp', + ] + elif CONFIG['COMPILE_ENVIRONMENT']: + error('Unknown C++ compiler, xptcall assembly will probably be incorrect.') + +if CONFIG['OS_ARCH'] == 'NetBSD': + if CONFIG['OS_TEST'] in ('amiga', 'atari', 'hp300', 'mac68k', 'mvme68k', + 'next68k', 'sun3', 'sun3x', 'x68k'): + SOURCES += [ + 'xptcinvoke_netbsd_m68k.cpp', + 'xptcstubs_netbsd_m68k.cpp' + ] + +if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD', 'OpenBSD'): + if CONFIG['OS_TEST'] == 'aarch64': + SOURCES += [ + 'xptcinvoke_aarch64.cpp', + 'xptcinvoke_asm_aarch64.s', + 'xptcstubs_aarch64.cpp', + 'xptcstubs_asm_aarch64.s', + ] + if CONFIG['OS_TEST'] == 'm68k': + SOURCES += [ + 'xptcinvoke_linux_m68k.cpp', + 'xptcstubs_linux_m68k.cpp', + ] + if 'mips' in CONFIG['OS_TEST']: + if 'mips64' in CONFIG['OS_TEST']: + SOURCES += [ + 'xptcinvoke_asm_mips64.S', + 'xptcinvoke_mips64.cpp', + 'xptcstubs_asm_mips64.S', + 'xptcstubs_mips64.cpp', + ] + else: + SOURCES += [ + 'xptcinvoke_asm_mips.S', + 'xptcinvoke_mips.cpp', + 'xptcstubs_asm_mips.S', + 'xptcstubs_mips.cpp', + ] + +if CONFIG['OS_ARCH'] == 'AIX': + if CONFIG['HAVE_64BIT_BUILD']: + SOURCES += [ + '!xptcstubs_asm_ppc_aix64.s', + 'xptcinvoke_asm_ppc_aix64.s', + 'xptcinvoke_ppc_aix64.cpp', + 'xptcstubs_ppc_aix64.cpp', + ] + else: + SOURCES += [ + '!xptcstubs_asm_ppc_aix.s', + 'xptcinvoke_ppc_aix.cpp', + 'xptcstubs_ppc_aix.cpp', + ] + if CONFIG['AIX_OBJMODEL'] == 'ibm': + SOURCES += [ + 'xptcinvoke_asm_ppc_ibmobj_aix.s', + ] + else: + SOURCES += [ + 'xptcinvoke_asm_ppc_aix.s', + ] + +if CONFIG['OS_TEST'] == 'powerpc': + if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'): + SOURCES += [ + 'xptcinvoke_asm_ppc_linux.S', + 'xptcinvoke_ppc_linux.cpp', + 'xptcstubs_asm_ppc_linux.S', + 'xptcstubs_ppc_linux.cpp', + ] + +if CONFIG['OS_TEST'] in ('powerpc64', 'powerpc64le'): + if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'): + SOURCES += [ + 'xptcinvoke_asm_ppc64_linux.S', + 'xptcinvoke_ppc64_linux.cpp', + 'xptcstubs_asm_ppc64_linux.S', + 'xptcstubs_ppc64_linux.cpp', + ] + +if CONFIG['OS_TEST'] in ('macppc', 'bebox', 'ofppc', 'prep', 'amigappc'): + if CONFIG['OS_ARCH'] == 'NetBSD': + SOURCES += [ + 'xptcinvoke_asm_ppc_netbsd.s', + 'xptcinvoke_ppc_netbsd.cpp', + 'xptcstubs_asm_ppc_netbsd.s', + 'xptcstubs_ppc_netbsd.cpp', + ] + +if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'powerpc': + SOURCES += [ + 'xptcinvoke_asm_ppc_openbsd.S', + 'xptcinvoke_ppc_openbsd.cpp', + 'xptcstubs_asm_ppc_openbsd.S', + 'xptcstubs_ppc_openbsd.cpp', + ] + +if CONFIG['OS_ARCH'] == 'Linux' and 'sparc' in CONFIG['OS_TEST']: + SOURCES += [ + 'xptcinvoke_asm_sparc_linux_GCC3.s', + 'xptcinvoke_sparc_solaris.cpp', + 'xptcstubs_asm_sparc_solaris.s', + 'xptcstubs_sparc_solaris.cpp', + ] + +if CONFIG['OS_ARCH'] == 'NetBSD' and CONFIG['OS_TEST'] == 'sparc': + SOURCES += [ + 'xptcinvoke_asm_sparc_netbsd.s', + 'xptcinvoke_sparc_netbsd.cpp', + 'xptcstubs_asm_sparc_netbsd.s', + 'xptcstubs_sparc_netbsd.cpp', + ] + +if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'sparc': + SOURCES += [ + 'xptcinvoke_asm_sparc_openbsd.s', + 'xptcinvoke_sparc_openbsd.cpp', + 'xptcstubs_asm_sparc_openbsd.s', + 'xptcstubs_sparc_openbsd.cpp', + ] + +if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD') and CONFIG['OS_TEST'] == 'sparc64': + SOURCES += [ + 'xptcinvoke_asm_sparc64_openbsd.s', + 'xptcinvoke_sparc64_openbsd.cpp', + 'xptcstubs_asm_sparc64_openbsd.s', + 'xptcstubs_sparc64_openbsd.cpp', + ] + +if CONFIG['OS_ARCH'] == 'SunOS' and '86' not in CONFIG['OS_TEST']: + if CONFIG['HAVE_64BIT_BUILD']: + ASFLAGS += ['-xarch=v9'] + SOURCES += [ + 'xptcinvoke_sparcv9_solaris.cpp', + 'xptcstubs_sparcv9_solaris.cpp', + ] + else: + SOURCES += [ + 'xptcinvoke_sparc_solaris.cpp', + 'xptcstubs_sparc_solaris.cpp', + ] + if CONFIG['GNU_CC']: + SOURCES += [ + 'xptcinvoke_asm_sparc_solaris_GCC3.s', + 'xptcstubs_asm_sparc_solaris.s', + ] + else: + if CONFIG['HAVE_64BIT_BUILD']: + SOURCES += [ + 'xptcinvoke_asm_sparcv9_solaris_SUNW.s', + 'xptcstubs_asm_sparcv9_solaris.s', + ] + else: + SOURCES += [ + 'xptcinvoke_asm_sparc_solaris_SUNW.s', + 'xptcstubs_asm_sparc_solaris.s', + ] + +if CONFIG['OS_ARCH'] == 'Linux': + if CONFIG['OS_TEST'] == 's390': + SOURCES += [ + 'xptcinvoke_linux_s390.cpp', + 'xptcstubs_linux_s390.cpp', + ] + CXXFLAGS += [ + '-fno-strict-aliasing', + '-fno-inline', + '-fomit-frame-pointer', + '-mbackchain', + ] + elif CONFIG['OS_TEST'] == 's390x': + SOURCES += [ + 'xptcinvoke_linux_s390x.cpp', + 'xptcstubs_linux_s390x.cpp', + ] + CXXFLAGS += [ + '-fno-strict-aliasing', + '-fno-inline', + '-fomit-frame-pointer', + '-mbackchain', + ] + +FINAL_LIBRARY = 'xul' + +LOCAL_INCLUDES += [ + '../..', + '/xpcom/reflect/xptinfo', +] + +NO_PGO = True diff --git a/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp new file mode 100644 index 000000000..0cb327a3d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* this code contributed by Bert Driehuis <bert_driehuis@nl.compuware.com> */ + +#include <stdio.h> + +// Try to determine the vtable layout generated by G++ +// Produces the offset at which the first vtable entry can be +// found, and the factor to apply for subsequent entries on stdout. +// Example output: +// #define GCC_VTABLE_START 0xc +// #define GCC_VTABLE_FACTOR 0x8 + +class test { +public: + virtual int t1(void); + virtual int t2(void); + int x; +}; + +test::test() { this->x = 0x12121212; }; + +int test::t1(void) { return 1; } +int test::t2(void) { return 2; } + +void die(char *x) { + fprintf(stderr, "%s\n", x); + exit(1); +} + +int +main() +{ + int i; + test *t = new test(); + int *tp = (int *) t; + int off1 = -1; + int off2 = -1; + int factor; + int factorshift; + + if (*tp++ != 0x12121212) + die("Integer element test::x not found!"); + tp = (int *) *tp; + for (i = 0; i < 10; i++) { + if (tp[i] == (int) t->t1) + off1 = i; + if (tp[i] == (int) t->t2) + off2 = i; + } + if (off1 == -1 || off2 == -1) + die("Could not determine offset into vtable!"); + factor = (off2 - off1) * 4; + factorshift = -1; + while (factor) { + factorshift++; + factor >>= 1; + } + printf("/* Automatically generated by vtable_layout_x86.cpp */\n"); + printf("#define GCC_VTABLE_START\t0x%x\n", off1 * 4); + printf("#define GCC_VTABLE_FACTOR\t0x%x\n", (off2 - off1) * 4); + printf("#define GCC_VTABLE_SHIFT\t0x%x\n", factorshift); + exit(0); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h new file mode 100644 index 000000000..733646c49 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h @@ -0,0 +1,17 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Special include file for xptc*_gcc_x86_unix.cpp */ + +// +// this may improve the static function calls, but may not. +// + +#ifdef MOZ_NEED_LEADING_UNDERSCORE +#define SYMBOL_UNDERSCORE "_" +#else +#define SYMBOL_UNDERSCORE +#endif + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp new file mode 100644 index 000000000..e5807dbcd --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp @@ -0,0 +1,140 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(__aarch64__) +#error "This code is for Linux AArch64 only." +#endif + + +/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections + * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the + * needed information. + * + * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf + */ + +#ifndef __AARCH64EL__ +#error "Only little endian compatibility was tested" +#endif + +/* + * Allocation of integer function arguments initially to registers r1-r7 + * and then to stack. Handling of 'that' argument which goes to register r0 + * is handled separately and does not belong here. + * + * 'ireg_args' - pointer to the current position in the buffer, + * corresponding to the register arguments + * 'stack_args' - pointer to the current position in the buffer, + * corresponding to the arguments on stack + * 'end' - pointer to the end of the registers argument + * buffer. + */ +static inline void alloc_word(uint64_t* &ireg_args, + uint64_t* &stack_args, + uint64_t* end, + uint64_t data) +{ + if (ireg_args < end) { + *ireg_args = data; + ireg_args++; + } else { + *stack_args = data; + stack_args++; + } +} + +static inline void alloc_double(double* &freg_args, + uint64_t* &stack_args, + double* end, + double data) +{ + if (freg_args < end) { + *freg_args = data; + freg_args++; + } else { + memcpy(stack_args, &data, sizeof(data)); + stack_args++; + } +} + +static inline void alloc_float(double* &freg_args, + uint64_t* &stack_args, + double* end, + float data) +{ + if (freg_args < end) { + memcpy(freg_args, &data, sizeof(data)); + freg_args++; + } else { + memcpy(stack_args, &data, sizeof(data)); + stack_args++; + } +} + + +extern "C" void +invoke_copy_to_stack(uint64_t* stk, uint64_t *end, + uint32_t paramCount, nsXPTCVariant* s) +{ + uint64_t *ireg_args = stk; + uint64_t *ireg_end = ireg_args + 8; + double *freg_args = (double *)ireg_end; + double *freg_end = freg_args + 8; + uint64_t *stack_args = (uint64_t *)freg_end; + + // leave room for 'that' argument in x0 + ++ireg_args; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + uint64_t word; + + if (s->IsPtrData()) { + word = (uint64_t)s->ptr; + } else { + // According to the ABI, integral types that are smaller than 8 + // bytes are to be passed in 8-byte registers or 8-byte stack + // slots. + switch (s->type) { + case nsXPTType::T_FLOAT: + alloc_float(freg_args, stack_args, freg_end, s->val.f); + continue; + case nsXPTType::T_DOUBLE: + alloc_double(freg_args, stack_args, freg_end, s->val.d); + continue; + case nsXPTType::T_I8: word = s->val.i8; break; + case nsXPTType::T_I16: word = s->val.i16; break; + case nsXPTType::T_I32: word = s->val.i32; break; + case nsXPTType::T_I64: word = s->val.i64; break; + case nsXPTType::T_U8: word = s->val.u8; break; + case nsXPTType::T_U16: word = s->val.u16; break; + case nsXPTType::T_U32: word = s->val.u32; break; + case nsXPTType::T_U64: word = s->val.u64; break; + case nsXPTType::T_BOOL: word = s->val.b; break; + case nsXPTType::T_CHAR: word = s->val.c; break; + case nsXPTType::T_WCHAR: word = s->val.wc; break; + default: + // all the others are plain pointer types + word = reinterpret_cast<uint64_t>(s->val.p); + break; + } + } + + alloc_word(ireg_args, stack_args, ireg_end, word); + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp new file mode 100644 index 000000000..dc111e435 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +__asm__("invoke_copy_to_stack") __attribute__((used)); + +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *d = (uint64_t)s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break; + case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break; + case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break; + case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break; + case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break; + case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break; + case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break; + case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // convert floats to doubles if they are to be passed + // via registers so we can just deal with doubles later + union { uint64_t u64; double d; } t; + t.d = (double)s->val.f; + *d = t.u64; + } + else + // otherwise copy to stack normally + *d = (uint64_t)s->val.u32; + break; + case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break; + case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break; + case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break; + default: + // all the others are plain pointer types + *d = (uint64_t)s->val.p; + break; + } + } +} + +/* + * EXPORT_XPCOM_API(nsresult) + * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ +__asm__( + "#### NS_InvokeByIndex ####\n" +".text\n\t" + ".align 5\n\t" + ".globl NS_InvokeByIndex\n\t" + ".ent NS_InvokeByIndex\n" +"NS_InvokeByIndex:\n\t" + ".frame $15,32,$26,0\n\t" + ".mask 0x4008000,-32\n\t" + "ldgp $29,0($27)\n" +"$NS_InvokeByIndex..ng:\n\t" + "subq $30,32,$30\n\t" + "stq $26,0($30)\n\t" + "stq $15,8($30)\n\t" + "bis $30,$30,$15\n\t" + ".prologue 1\n\t" + + /* + * Allocate enough stack space to hold the greater of 6 or "paramCount"+1 + * parameters. (+1 for "this" pointer) Room for at least 6 parameters + * is required for storage of those passed via registers. + */ + + "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */ + "cmplt $2,$18,$1\n\t" + "cmovne $1,$18,$2\n\t" + "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */ + "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */ + "subq $30,$1,$30\n\t" + + "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */ + "stq $17,16($15)\n\t" /* save "methodIndex" */ + + "addq $30,8,$16\n\t" /* pass stack pointer */ + "bis $18,$18,$17\n\t" /* pass "paramCount" */ + "bis $19,$19,$18\n\t" /* pass "params" */ + "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */ + + /* + * Copy the first 6 parameters to registers and remove from stack frame. + * Both the integer and floating point registers are set for each parameter + * except the first which is the "this" pointer. (integer only) + * The floating point registers are all set as doubles since the + * invoke_copy_to_stack function should have converted the floats. + */ + "ldq $16,0($30)\n\t" /* integer registers */ + "ldq $17,8($30)\n\t" + "ldq $18,16($30)\n\t" + "ldq $19,24($30)\n\t" + "ldq $20,32($30)\n\t" + "ldq $21,40($30)\n\t" + "ldt $f17,8($30)\n\t" /* floating point registers */ + "ldt $f18,16($30)\n\t" + "ldt $f19,24($30)\n\t" + "ldt $f20,32($30)\n\t" + "ldt $f21,40($30)\n\t" + + "addq $30,48,$30\n\t" /* remove params from stack */ + + /* + * Call the virtual function with the constructed stack frame. + */ + "bis $16,$16,$1\n\t" /* load "this" */ + "ldq $2,16($15)\n\t" /* load "methodIndex" */ + "ldq $1,0($1)\n\t" /* load vtable */ + "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */ + "addq $1,$2,$1\n\t" + "ldq $27,0($1)\n\t" /* load address of function */ + "jsr $26,($27),0\n\t" /* call virtual function */ + "ldgp $29,0($26)\n\t" + + "bis $15,$15,$30\n\t" + "ldq $26,0($30)\n\t" + "ldq $15,8($30)\n\t" + "addq $30,32,$30\n\t" + "ret $31,($26),1\n\t" + ".end NS_InvokeByIndex" + ); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp new file mode 100644 index 000000000..4cd5eb47d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp @@ -0,0 +1,417 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#include "mozilla/Compiler.h" + +#if !defined(__arm__) && !(defined(LINUX) || defined(ANDROID) || defined(XP_IOS)) +#error "This code is for Linux/iOS ARM only. Check that it works on your system, too.\nBeware that this code is highly compiler dependent." +#endif + +#if MOZ_IS_GCC +#if defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP) && !defined(__ARM_PCS) +#error "Can't identify floating point calling conventions.\nPlease ensure that your toolchain defines __ARM_PCS or __ARM_PCS_VFP." +#endif +#endif + +#ifndef __ARM_PCS_VFP + +/* This function copies a 64-bits word from dw to the given pointer in + * a buffer delimited by start and end, possibly wrapping around the + * buffer boundaries, and/or properly aligning the data at 64-bits word + * boundaries (for EABI). + * start and end are both assumed to be 64-bits aligned. + * Returns a pointer to the second 32-bits word copied (to accomodate + * the invoke_copy_to_stack loop). + */ +static uint32_t * +copy_double_word(uint32_t *start, uint32_t *current, uint32_t *end, uint64_t *dw) +{ +#ifdef __ARM_EABI__ + /* Aligning the pointer for EABI */ + current = (uint32_t *)(((uint32_t)current + 7) & ~7); + /* Wrap when reaching the end of the buffer */ + if (current == end) current = start; +#else + /* On non-EABI, 64-bits values are not aligned and when we reach the end + * of the buffer, we need to write half of the data at the end, and the + * other half at the beginning. */ + if (current == end - 1) { + *current = ((uint32_t*)dw)[0]; + *start = ((uint32_t*)dw)[1]; + return start; + } +#endif + + *((uint64_t*) current) = *dw; + return current + 1; +} + +/* See stack_space comment in NS_InvokeByIndex to see why this needs not to + * be static on DEBUG builds. */ +#ifndef DEBUG +static +#endif +void +invoke_copy_to_stack(uint32_t* stk, uint32_t *end, + uint32_t paramCount, nsXPTCVariant* s) +{ + /* The stack buffer is 64-bits aligned. The end argument points to its end. + * The caller is assumed to create a stack buffer of at least four 32-bits + * words. + * We use the last three 32-bit words to store the values for r1, r2 and r3 + * for the method call, i.e. the first words for arguments passing. + */ + uint32_t *d = end - 3; + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + /* Wrap when reaching the end of the stack buffer */ + if (d == end) d = stk; + NS_ASSERTION(d >= stk && d < end, + "invoke_copy_to_stack is copying outside its given buffer"); + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + // According to the ARM EABI, integral types that are smaller than a word + // are to be sign/zero-extended to a full word and treated as 4-byte values. + + switch(s->type) + { + case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : + d = copy_double_word(stk, d, end, (uint64_t *)&s->val.i64); + break; + case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : + d = copy_double_word(stk, d, end, (uint64_t *)&s->val.u64); + break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : + d = copy_double_word(stk, d, end, (uint64_t *)&s->val.d); + break; + case nsXPTType::T_BOOL : *((int32_t*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t); + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + +/* This is to call a given method of class that. + * The parameters are in params, the number is in paramCount. + * The routine will issue calls to count the number of words + * required for argument passing and to copy the arguments to + * the stack. + * ACPS passes the first 3 params in r1-r3 (with exceptions for 64-bits + * arguments), and the remaining goes onto the stack. + * We allocate a buffer on the stack for a "worst case" estimate of how much + * stack might be needed for EABI, i.e. twice the number of parameters. + * The end of this buffer will be used to store r1 to r3, so that the start + * of the stack is the remaining parameters. + * The magic here is to call the method with "that" and three 32-bits + * arguments corresponding to r1-r3, so that the compiler generates the + * proper function call. The stack will also contain the remaining arguments. + * + * !!! IMPORTANT !!! + * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented + * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])! + * + */ + + vtable_func *vtable, func; + int base_size = (paramCount > 1) ? paramCount : 2; + +/* !!! IMPORTANT !!! + * On DEBUG builds, the NS_ASSERTION used in invoke_copy_to_stack needs to use + * the stack to pass the 5th argument to NS_DebugBreak. When invoke_copy_to_stack + * is inlined, this can result, depending on the compiler and flags, in the + * stack pointer not pointing at stack_space when the method is called at the + * end of this function. More generally, any function call requiring stack + * allocation of arguments is unsafe to be inlined in this function. + */ + uint32_t *stack_space = (uint32_t *) __builtin_alloca(base_size * 8); + + invoke_copy_to_stack(stack_space, &stack_space[base_size * 2], + paramCount, params); + + vtable = *reinterpret_cast<vtable_func **>(that); + func = vtable[methodIndex]; + + return func(that, stack_space[base_size * 2 - 3], + stack_space[base_size * 2 - 2], + stack_space[base_size * 2 - 1]); +} + +#else /* __ARM_PCS_VFP */ + +/* "Procedure Call Standard for the ARM Architecture" document, sections + * "5.5 Parameter Passing" and "6.1.2 Procedure Calling" contain all the + * needed information. + * + * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf + */ + +#if defined(__thumb__) && !defined(__thumb2__) +#error "Thumb1 is not supported" +#endif + +#ifndef __ARMEL__ +#error "Only little endian compatibility was tested" +#endif + +/* + * Allocation of integer function arguments initially to registers r1-r3 + * and then to stack. Handling of 'this' argument which goes to r0 registers + * is handled separately and does not belong to these two inline functions. + * + * The doubleword arguments are allocated to even:odd + * register pairs or get aligned at 8-byte boundary on stack. The "holes" + * which may appear as a result of this realignment remain unused. + * + * 'ireg_args' - pointer to the current position in the buffer, + * corresponding to the register arguments + * 'stack_args' - pointer to the current position in the buffer, + * corresponding to the arguments on stack + * 'end' - pointer to the end of the registers argument + * buffer (it is guaranteed to be 8-bytes aligned) + */ + +static inline void copy_word(uint32_t* &ireg_args, + uint32_t* &stack_args, + uint32_t* end, + uint32_t data) +{ + if (ireg_args < end) { + *ireg_args = data; + ireg_args++; + } else { + *stack_args = data; + stack_args++; + } +} + +static inline void copy_dword(uint32_t* &ireg_args, + uint32_t* &stack_args, + uint32_t* end, + uint64_t data) +{ + if (ireg_args + 1 < end) { + if ((uint32_t)ireg_args & 4) { + ireg_args++; + } + *(uint64_t *)ireg_args = data; + ireg_args += 2; + } else { + ireg_args = end; + if ((uint32_t)stack_args & 4) { + stack_args++; + } + *(uint64_t *)stack_args = data; + stack_args += 2; + } +} + +/* + * Allocation of floating point arguments to VFP registers (s0-s15, d0-d7). + * + * Unlike integer registers allocation, "back-filling" needs to be + * supported. For example, the third floating point argument in the + * following function is going to be allocated to s1 register, back-filling + * the "hole": + * void f(float s0, double d1, float s1) + * + * Refer to the "Procedure Call Standard for the ARM Architecture" document + * for more details. + * + * 'vfp_s_args' - pointer to the current position in the buffer with + * the next unallocated single precision register + * 'vfp_d_args' - pointer to the current position in the buffer with + * the next unallocated double precision register, + * it has the same value as 'vfp_s_args' when back-filling + * is not used + * 'end' - pointer to the end of the vfp registers argument + * buffer (it is guaranteed to be 8-bytes aligned) + * + * Mozilla bugtracker has a test program attached which be used for + * experimenting with VFP registers allocation code and testing its + * correctness: + * https://bugzilla.mozilla.org/show_bug.cgi?id=601914#c19 + */ + +static inline bool copy_vfp_single(float* &vfp_s_args, double* &vfp_d_args, + float* end, float data) +{ + if (vfp_s_args >= end) + return false; + + *vfp_s_args = data; + vfp_s_args++; + if (vfp_s_args < (float *)vfp_d_args) { + // It was the case of back-filling, now the next free single precision + // register should overlap with the next free double precision register + vfp_s_args = (float *)vfp_d_args; + } else if (vfp_s_args > (float *)vfp_d_args) { + // also update the pointer to the next free double precision register + vfp_d_args++; + } + return true; +} + +static inline bool copy_vfp_double(float* &vfp_s_args, double* &vfp_d_args, + float* end, double data) +{ + if (vfp_d_args >= (double *)end) { + // The back-filling continues only so long as no VFP CPRC has been + // allocated to a slot on the stack. Basically no VFP registers can + // be allocated after this point. + vfp_s_args = end; + return false; + } + + if (vfp_s_args == (float *)vfp_d_args) { + // also update the pointer to the next free single precision register + vfp_s_args += 2; + } + *vfp_d_args = data; + vfp_d_args++; + return true; +} + +static void +invoke_copy_to_stack(uint32_t* stk, uint32_t *end, + uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t *ireg_args = end - 3; + float *vfp_s_args = (float *)end; + double *vfp_d_args = (double *)end; + float *vfp_end = vfp_s_args + 16; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsPtrData()) { + copy_word(ireg_args, stk, end, (uint32_t)s->ptr); + continue; + } + // According to the ARM EABI, integral types that are smaller than a word + // are to be sign/zero-extended to a full word and treated as 4-byte values + switch (s->type) + { + case nsXPTType::T_FLOAT: + if (!copy_vfp_single(vfp_s_args, vfp_d_args, vfp_end, s->val.f)) { + copy_word(end, stk, end, reinterpret_cast<uint32_t&>(s->val.f)); + } + break; + case nsXPTType::T_DOUBLE: + if (!copy_vfp_double(vfp_s_args, vfp_d_args, vfp_end, s->val.d)) { + copy_dword(end, stk, end, reinterpret_cast<uint64_t&>(s->val.d)); + } + break; + case nsXPTType::T_I8: copy_word(ireg_args, stk, end, s->val.i8); break; + case nsXPTType::T_I16: copy_word(ireg_args, stk, end, s->val.i16); break; + case nsXPTType::T_I32: copy_word(ireg_args, stk, end, s->val.i32); break; + case nsXPTType::T_I64: copy_dword(ireg_args, stk, end, s->val.i64); break; + case nsXPTType::T_U8: copy_word(ireg_args, stk, end, s->val.u8); break; + case nsXPTType::T_U16: copy_word(ireg_args, stk, end, s->val.u16); break; + case nsXPTType::T_U32: copy_word(ireg_args, stk, end, s->val.u32); break; + case nsXPTType::T_U64: copy_dword(ireg_args, stk, end, s->val.u64); break; + case nsXPTType::T_BOOL: copy_word(ireg_args, stk, end, s->val.b); break; + case nsXPTType::T_CHAR: copy_word(ireg_args, stk, end, s->val.c); break; + case nsXPTType::T_WCHAR: copy_word(ireg_args, stk, end, s->val.wc); break; + default: + // all the others are plain pointer types + copy_word(ireg_args, stk, end, reinterpret_cast<uint32_t>(s->val.p)); + break; + } + } +} + +typedef uint32_t (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); + vtable_func func = vtable[methodIndex]; + // 'register uint32_t result asm("r0")' could be used here, but it does not + // seem to be reliable in all cases: http://gcc.gnu.org/PR46164 + nsresult result; + asm ( + "mov r3, sp\n" + "mov %[stack_space_size], %[param_count_plus_2], lsl #3\n" + "tst r3, #4\n" /* check stack alignment */ + + "add %[stack_space_size], #(4 * 16)\n" /* space for VFP registers */ + "mov r3, %[params]\n" + + "it ne\n" + "addne %[stack_space_size], %[stack_space_size], #4\n" + "sub r0, sp, %[stack_space_size]\n" /* allocate space on stack */ + + "sub r2, %[param_count_plus_2], #2\n" + "mov sp, r0\n" + + "add r1, r0, %[param_count_plus_2], lsl #3\n" + "blx %[invoke_copy_to_stack]\n" + + "add ip, sp, %[param_count_plus_2], lsl #3\n" + "mov r0, %[that]\n" + "ldmdb ip, {r1, r2, r3}\n" + "vldm ip, {d0, d1, d2, d3, d4, d5, d6, d7}\n" + "blx %[func]\n" + + "add sp, sp, %[stack_space_size]\n" /* cleanup stack */ + "mov %[stack_space_size], r0\n" /* it's actually 'result' variable */ + : [stack_space_size] "=&r" (result) + : [func] "r" (func), + [that] "r" (that), + [params] "r" (params), + [param_count_plus_2] "r" (paramCount + 2), + [invoke_copy_to_stack] "r" (invoke_copy_to_stack) + : "cc", "memory", + // Mark all the scratch registers as clobbered because they may be + // modified by the functions, called from this inline assembly block + "r0", "r1", "r2", "r3", "ip", "lr", + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", + // Also unconditionally mark d16-d31 registers as clobbered even though + // they actually don't exist in vfpv2 and vfpv3-d16 variants. There is + // no way to identify VFP variant using preprocessor at the momemnt + // (see http://gcc.gnu.org/PR46128 for more details), but fortunately + // current versions of gcc do not seem to complain about these registers + // even when this code is compiled with '-mfpu=vfpv3-d16' option. + // If gcc becomes more strict in the future and/or provides a way to + // identify VFP variant, the following d16-d31 registers list needs + // to be wrapped into some #ifdef + "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", + "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31" + ); + return result; +} + +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp new file mode 100644 index 000000000..1b0c214ea --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp @@ -0,0 +1,181 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +// Remember that these 'words' are 32bit DWORDS + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; +} + +static void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" +struct my_params_struct { + nsISupports* that; + uint32_t Index; + uint32_t Count; + nsXPTCVariant* params; + uint32_t fn_count; + uint32_t fn_copy; +}; + +XPTC_PUBLIC_API(nsresult) +XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + uint32_t result; + struct my_params_struct my_params; + my_params.that = that; + my_params.Index = methodIndex; + my_params.Count = paramCount; + my_params.params = params; + my_params.fn_copy = (uint32_t) &invoke_copy_to_stack; + my_params.fn_count = (uint32_t) &invoke_count_words; + +/* This is to call a given method of class that. + * The parameters are in params, the number is in paramCount. + * The routine will issue calls to count the number of words + * required for argument passing and to copy the arguments to + * the stack. + * Since APCS passes the first 3 params in r1-r3, we need to + * load the first three words from the stack and correct the stack + * pointer (sp) in the appropriate way. This means: + * + * 1.) more than 3 arguments: load r1-r3, correct sp and remember No. + * of bytes left on the stack in r4 + * + * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope), + * restore sp as if nothing had happened and set the marker r4 to zero. + * + * Afterwards sp will be restored using the value in r4 (which is not a temporary register + * and will be preserved by the function/method called according to APCS [ARM Procedure + * Calling Standard]). + * + * !!! IMPORTANT !!! + * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented + * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])! + * + */ + + __asm__ __volatile__( + "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */ + "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */ + "ldr r0, [%1, #8] \n\t" + "mov lr, pc \n\t" /* call it... */ + "mov pc, ip \n\t" + "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */ + "sub sp, sp, r4 \n\t" /* use stack space for the args... */ + "mov r0, sp \n\t" /* prepare a pointer an the stack */ + "ldr r1, [%1, #8] \n\t" /* =paramCount */ + "ldr r2, [%1, #12] \n\t" /* =params */ + "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */ + "mov lr, pc \n\t" /* copy args to the stack like the */ + "mov pc, ip \n\t" /* compiler would. */ + "ldr r0, [%1] \n\t" /* =that */ + "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */ + "ldr r2, [%1, #4] \n\t" + "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */ + "add r2, r2, #8 \n\t" /* with this compilers */ + "ldr r3, [r2] \n\t" /* get virtual offset from vtable */ + "mov r3, r3, lsl #16 \n\t" + "add r0, r0, r3, asr #16\n\t" + "ldr ip, [r2, #4] \n\t" /* get method address from vtable */ + "cmp r4, #12 \n\t" /* more than 3 arguments??? */ + "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */ + "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */ + "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */ + "addle sp, sp, r4 \n\t" /* and restore stack pointer */ + "movle r4, #0 \n\t" /* a mark for restoring sp */ + "mov lr, pc \n\t" /* call mathod */ + "mov pc, ip \n\t" + "add sp, sp, r4 \n\t" /* restore stack pointer */ + "mov %0, r0 \n\t" /* the result... */ + : "=r" (result) + : "r" (&my_params) + : "r0", "r1", "r2", "r3", "r4", "ip", "lr" + ); + + return result; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp new file mode 100644 index 000000000..4ec7dd20f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +// Remember that these 'words' are 32bit DWORDS + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; +} + +static void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" { + struct my_params_struct { + nsISupports* that; + uint32_t Index; + uint32_t Count; + nsXPTCVariant* params; + uint32_t fn_count; + uint32_t fn_copy; + }; +} + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + uint32_t result; + struct my_params_struct my_params; + my_params.that = that; + my_params.Index = methodIndex; + my_params.Count = paramCount; + my_params.params = params; + my_params.fn_copy = (uint32_t) &invoke_copy_to_stack; + my_params.fn_count = (uint32_t) &invoke_count_words; + +/* This is to call a given method of class that. + * The parameters are in params, the number is in paramCount. + * The routine will issue calls to count the number of words + * required for argument passing and to copy the arguments to + * the stack. + * Since APCS passes the first 3 params in r1-r3, we need to + * load the first three words from the stack and correct the stack + * pointer (sp) in the appropriate way. This means: + * + * 1.) more than 3 arguments: load r1-r3, correct sp and remember No. + * of bytes left on the stack in r4 + * + * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope), + * restore sp as if nothing had happened and set the marker r4 to zero. + * + * Afterwards sp will be restored using the value in r4 (which is not a temporary register + * and will be preserved by the function/method called according to APCS [ARM Procedure + * Calling Standard]). + * + * !!! IMPORTANT !!! + * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented + * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])! + * + */ + +#ifdef __GNUC__ + __asm__ __volatile__( + "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */ + "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */ + "ldr r0, [%1, #8] \n\t" + "mov lr, pc \n\t" /* call it... */ + "mov pc, ip \n\t" + "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */ + "sub sp, sp, r4 \n\t" /* use stack space for the args... */ + "mov r0, sp \n\t" /* prepare a pointer an the stack */ + "ldr r1, [%1, #8] \n\t" /* =paramCount */ + "ldr r2, [%1, #12] \n\t" /* =params */ + "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */ + "mov lr, pc \n\t" /* copy args to the stack like the */ + "mov pc, ip \n\t" /* compiler would. */ + "ldr r0, [%1] \n\t" /* =that */ + "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */ + "ldr r2, [%1, #4] \n\t" + "mov r2, r2, lsl #2 \n\t" /* a vtable_entry(x)=8 + (4 bytes * x) */ + "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */ + "cmp r4, #12 \n\t" /* more than 3 arguments??? */ + "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */ + "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */ + "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */ + "addle sp, sp, r4 \n\t" /* and restore stack pointer */ + "movle r4, #0 \n\t" /* a mark for restoring sp */ + "ldr r0, [%1, #0] \n\t" /* get (self) */ + "mov lr, pc \n\t" /* call mathod */ + "mov pc, ip \n\t" + "add sp, sp, r4 \n\t" /* restore stack pointer */ + "mov %0, r0 \n\t" /* the result... */ + : "=r" (result) + : "r" (&my_params), "m" (my_params) + : "r0", "r1", "r2", "r3", "r4", "ip", "lr", "sp" + ); +#else +#error "Unsupported compiler. Use g++ >= 2.8 for OpenBSD/arm." +#endif /* G++ >= 2.8 */ + + return result; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s new file mode 100644 index 000000000..efe691a68 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .section ".text" + .globl _NS_InvokeByIndex + .type _NS_InvokeByIndex,@function + +/* + * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ + +_NS_InvokeByIndex: + # set up frame + stp x29, x30, [sp,#-32]! + mov x29, sp + stp x19, x20, [sp,#16] + + # save methodIndex across function calls + mov w20, w1 + + # end of stack area passed to invoke_copy_to_stack + mov x1, sp + + # assume 8 bytes of stack for each argument with 16-byte alignment + add w19, w2, #1 + and w19, w19, #0xfffffffe + sub sp, sp, w19, uxth #3 + + # temporary place to store args passed in r0-r7,v0-v7 + sub sp, sp, #128 + + # save 'that' on stack + str x0, [sp] + + # start of stack area passed to invoke_copy_to_stack + mov x0, sp + bl invoke_copy_to_stack + + # load arguments passed in r0-r7 + ldp x6, x7, [sp, #48] + ldp x4, x5, [sp, #32] + ldp x2, x3, [sp, #16] + ldp x0, x1, [sp],#64 + + # load arguments passed in v0-v7 + ldp d6, d7, [sp, #48] + ldp d4, d5, [sp, #32] + ldp d2, d3, [sp, #16] + ldp d0, d1, [sp],#64 + + # call the method + ldr x16, [x0] + add x16, x16, w20, uxth #3 + ldr x16, [x16] + blr x16 + + add sp, sp, w19, uxth #3 + ldp x19, x20, [sp,#16] + ldp x29, x30, [sp],#32 + ret + + .size _NS_InvokeByIndex, . - _NS_InvokeByIndex + + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s new file mode 100644 index 000000000..794c4f5c1 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s @@ -0,0 +1,145 @@ + +// Select C numeric constant + .radix C +// for 64 bit mode, use .psr abi64 + .psr abi32 +// big endian + .psr msb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'NS_InvokeByIndex' + .proc NS_InvokeByIndex +// manual bundling + .explicit + +// extern "C" uint32_t +// invoke_copy_to_stack(uint64_t* d, +// const uint32_t paramCount, nsXPTCVariant* s) + .global invoke_copy_to_stack +// .exclass invoke_copy_to_stack, @fullyvisible + .type invoke_copy_to_stack,@function + +// .exclass NS_InvokeByIndex, @fullyvisible + .type NS_InvokeByIndex,@function + +// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params); +NS_InvokeByIndex:: + .prologue + .save ar.pfs, r37 +// allocate 4 input args, 6 local args, and 8 output args + alloc r37 = ar.pfs, 4, 6, 8, 0 // M + nop.i 0 ;; // I + +// unwind table already knows gp, no need to specify anything + add r39 = 0, gp // A + .save rp, r36 + mov r36 = rp // I + .vframe r38 + add r38 = 0, sp ;; // A + +// We first calculate the amount of extra memory stack space required +// for the arguments, and register storage. +// We then call invoke_copy_to_stack() to write the argument contents +// to the specified memory regions. +// We then copy the integer arguments to integer registers, and floating +// arguments to float registers. +// Lastly we load the virtual table jump pointer, and call the target +// subroutine. + +// in0 : that +// in1 : methodIndex +// in2 : paramCount +// in3 : params + +// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64 +// 16 byte frame header +// 8 * even(paramCount) memory argument area +// 64 bytes integer register area +// 64 bytes float register area +// This scheme makes sure stack fram size is a multiple of 16 + + .body + add r10 = 8, r0 // A +// r41 points to float register area + add r41 = -64, sp // A +// r40 points to int register area + add r40 = -128, sp ;; // A + + add out1 = 0, r40 // A + add out2 = 0, r41 // A + tbit.z p14,p15 = in2,0 ;; // I + +// compute 8 * even(paramCount) +(p14) shladd r11 = in2, 3, r0 ;; // A +(p15) shladd r11 = in2, 3, r10 ;; // A + sub out0 = r40, r11 ;; // A + +// advance the stack frame + add sp = -16, out0 // A + add out3 = 0, in2 // A + add out4 = 0, in3 // A + +// branch to invoke_copy_to_stack + br.call.sptk.few rp = invoke_copy_to_stack ;; // B + +// restore gp + add gp = 0, r39 // A + add out0 = 0, in0 // A + +// load the integer and float registers + ld8 out1 = [r40], 8 // M + ldfd f8 = [r41], 8 ;; // M + + ld8 out2 = [r40], 8 // M + ldfd f9 = [r41], 8 ;; // M + + ld8 out3 = [r40], 8 // M + ldfd f10 = [r41], 8 ;; // M + + ld8 out4 = [r40], 8 // M + ldfd f11 = [r41], 8 ;; // M + + ld8 out5 = [r40], 8 // M + ldfd f12 = [r41], 8 ;; // M +// 16 * methodIndex + shladd r11 = in1, 4, r0 // A + + ld8 out6 = [r40], 8 // M + ldfd f13 = [r41], 8 ;; // M + + ld8 out7 = [r40], 8 // M + ldfd f14 = [r41], 8 // M + addp4 r8 = 0, in0 ;; // A + +// look up virtual base table and dispatch to target subroutine +// This section assumes 32 bit pointer mode, and virtual base table +// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html + +// load base table + ld4 r8 = [r8] ;; // M + addp4 r8 = r11, r8 ;; // A + + // first entry is jump pointer, second entry is gp + addp4 r9 = 8, r8 ;; // A +// load jump pointer + ld8 r8 = [r8] + +// load gp + ld8 gp = [r9] ;; // M + mov b6 = r8 ;; // I + +// branch to target virtual function + br.call.sptk.few rp = b6 ;; // B + +// epilog + mov ar.pfs = r37 // I + mov rp = r36 ;; // I + + add sp = 0, r38 // A + add gp = 0, r39 // A + br.ret.sptk.few rp ;; // B + + .endp + + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s new file mode 100644 index 000000000..140c44117 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s @@ -0,0 +1,146 @@ + +// Select C numeric constant + .radix C +// for 64 bit mode, use .psr abi64 + .psr abi64 +// little endian + .psr lsb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'NS_InvokeByIndex' + .proc NS_InvokeByIndex +// manual bundling + .explicit + +// extern "C" uint32_t +// invoke_copy_to_stack(uint64_t* d, +// const uint32_t paramCount, nsXPTCVariant* s) + .global invoke_copy_to_stack +// .exclass invoke_copy_to_stack, @fullyvisible + .type invoke_copy_to_stack,@function + +// .exclass NS_InvokeByIndex, @fullyvisible + .type NS_InvokeByIndex,@function + +// XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params); +NS_InvokeByIndex:: + .prologue + .save ar.pfs, r37 +// allocate 4 input args, 6 local args, and 8 output args + alloc r37 = ar.pfs, 4, 6, 8, 0 // M + nop.i 0 ;; // I + +// unwind table already knows gp, no need to specify anything + add r39 = 0, gp // A + .save rp, r36 + mov r36 = rp // I + .vframe r38 + add r38 = 0, sp ;; // A + +// We first calculate the amount of extra memory stack space required +// for the arguments, and register storage. +// We then call invoke_copy_to_stack() to write the argument contents +// to the specified memory regions. +// We then copy the integer arguments to integer registers, and floating +// arguments to float registers. +// Lastly we load the virtual table jump pointer, and call the target +// subroutine. + +// in0 : that +// in1 : methodIndex +// in2 : paramCount +// in3 : params + +// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64 +// 16 byte frame header +// 8 * even(paramCount) memory argument area +// 64 bytes integer register area +// 64 bytes float register area +// This scheme makes sure stack fram size is a multiple of 16 + + .body + add r10 = 8, r0 // A +// r41 points to float register area + add r41 = -64, sp // A +// r40 points to int register area + add r40 = -128, sp ;; // A + + add out1 = 0, r40 // A + add out2 = 0, r41 // A + tbit.z p14,p15 = in2,0 ;; // I + +// compute 8 * even(paramCount) +(p14) shladd r11 = in2, 3, r0 ;; // A +(p15) shladd r11 = in2, 3, r10 ;; // A + sub out0 = r40, r11 ;; // A + +// advance the stack frame + add sp = -16, out0 // A + add out3 = 0, in2 // A + add out4 = 0, in3 // A + +// branch to invoke_copy_to_stack + br.call.sptk.few rp = invoke_copy_to_stack ;; // B + +// restore gp + add gp = 0, r39 // A + add out0 = 0, in0 // A + +// load the integer and float registers + ld8 out1 = [r40], 8 // M + ldfd f8 = [r41], 8 ;; // M + + ld8 out2 = [r40], 8 // M + ldfd f9 = [r41], 8 ;; // M + + ld8 out3 = [r40], 8 // M + ldfd f10 = [r41], 8 ;; // M + + ld8 out4 = [r40], 8 // M + ldfd f11 = [r41], 8 ;; // M + + ld8 out5 = [r40], 8 // M + ldfd f12 = [r41], 8 ;; // M +// 16 * methodIndex + shladd r11 = in1, 4, r0 // A + + ld8 out6 = [r40], 8 // M + ldfd f13 = [r41], 8 ;; // M + + ld8 out7 = [r40], 8 // M + ldfd f14 = [r41], 8 // M + add r8 = 0, in0 ;; // A + +// look up virtual base table and dispatch to target subroutine +// This section assumes 64 bit pointer mode, and virtual base table +// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html + +// load base table + ld8 r8 = [r8] ;; // M + add r8 = r11, r8 ;; // A + + // first entry is jump pointer, second entry is gp + add r9 = 8, r8 ;; // A +// load jump pointer + ld8 r8 = [r8] + +// load gp + ld8 gp = [r9] ;; // M + mov b6 = r8 ;; // I + +// branch to target virtual function + br.call.sptk.few rp = b6 ;; // B + +// epilog + mov ar.pfs = r37 // I + mov rp = r36 ;; // I + + add sp = 0, r38 // A + add gp = 0, r39 // A + br.ret.sptk.few rp ;; // B + + .endp + +/* Magic indicating no need for an executable stack */ +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S new file mode 100644 index 000000000..32ff3b356 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S @@ -0,0 +1,134 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +#ifdef ANDROID +#include <asm/regdef.h> +#include <asm/asm.h> +#include <machine/asm.h> +#else +#include <sys/regdef.h> +#include <sys/asm.h> +#endif + +# NARGSAVE is the argument space in the callers frame, including extra +# 'shadowed' space for the argument registers. The minimum of 4 +# argument slots is sometimes predefined in the header files. +#ifndef NARGSAVE +#define NARGSAVE 4 +#endif + +#define LOCALSZ 3 /* gp, fp, ra */ +#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK) + +#define RAOFF (FRAMESZ - (1*SZREG)) +#define FPOFF (FRAMESZ - (2*SZREG)) +#define GPOFF (FRAMESZ - (3*SZREG)) + +#define A0OFF (FRAMESZ + (0*SZREG)) +#define A1OFF (FRAMESZ + (1*SZREG)) +#define A2OFF (FRAMESZ + (2*SZREG)) +#define A3OFF (FRAMESZ + (3*SZREG)) + + .text + +# +# _NS_InvokeByIndex(that, methodIndex, paramCount, params) +# a0 a1 a2 a3 + + .globl _NS_InvokeByIndex + .align 2 + .type _NS_InvokeByIndex,@function + .ent _NS_InvokeByIndex,0 + .frame fp, FRAMESZ, ra +_NS_InvokeByIndex: + SETUP_GP + subu sp, FRAMESZ + + # specify the save register mask for gp, fp, ra, a3 - a0 + .mask 0xD00000F0, RAOFF-FRAMESZ + + sw ra, RAOFF(sp) + sw fp, FPOFF(sp) + + # we can't use .cprestore in a variable stack frame + sw gp, GPOFF(sp) + + sw a0, A0OFF(sp) + sw a1, A1OFF(sp) + sw a2, A2OFF(sp) + sw a3, A3OFF(sp) + + # save bottom of fixed frame + move fp, sp + + # extern "C" uint32 + # invoke_count_words(uint32_t paramCount, nsXPTCVariant* s); + la t9, invoke_count_words + move a0, a2 + move a1, a3 + jalr t9 + lw gp, GPOFF(fp) + + # allocate variable stack, with a size of: + # wordsize (of 4 bytes) * result (already aligned to dword) + # but a minimum of 16 byte + sll v0, 2 + slt t0, v0, 16 + beqz t0, 1f + li v0, 16 +1: subu sp, v0 + + # let a0 point to the bottom of the variable stack, allocate + # another fixed stack for: + # extern "C" void + # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + # nsXPTCVariant* s); + la t9, invoke_copy_to_stack + move a0, sp + lw a1, A2OFF(fp) + lw a2, A3OFF(fp) + subu sp, 16 + jalr t9 + lw gp, GPOFF(fp) + + # back to the variable stack frame + addu sp, 16 + + # calculate the function we need to jump to, which must then be + # stored in t9 + lw a0, A0OFF(fp) # a0 = set "that" to be "this" + lw t0, A1OFF(fp) # a1 = methodIndex + lw t9, 0(a0) + # t0 = methodIndex << PTRLOG + sll t0, t0, PTRLOG + addu t9, t0 + lw t9, (t9) + + # Set a1-a3 to what invoke_copy_to_stack told us. a0 is already + # the "this" pointer. We don't have to care about floating + # point arguments, the non-FP "this" pointer as first argument + # means they'll never be used. + lw a1, 1*SZREG(sp) + lw a2, 2*SZREG(sp) + lw a3, 3*SZREG(sp) + + jalr t9 + # Micro-optimization: There's no gp usage below this point, so + # we don't reload. + # lw gp, GPOFF(fp) + + # leave variable stack frame + move sp, fp + + lw ra, RAOFF(sp) + lw fp, FPOFF(sp) + + addiu sp, FRAMESZ + j ra +END(_NS_InvokeByIndex) diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S new file mode 100644 index 000000000..eef34de7f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S @@ -0,0 +1,122 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <sys/regdef.h> +#include <sys/asm.h> + +.text +.globl invoke_count_words +.globl invoke_copy_to_stack + +LOCALSZ=7 # a0, a1, a2, a3, s0, ra, gp +FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK + +RAOFF=FRAMESZ-(1*SZREG) +A0OFF=FRAMESZ-(2*SZREG) +A1OFF=FRAMESZ-(3*SZREG) +A2OFF=FRAMESZ-(4*SZREG) +A3OFF=FRAMESZ-(5*SZREG) +S0OFF=FRAMESZ-(6*SZREG) +GPOFF=FRAMESZ-(7*SZREG) + +# +# _NS_InvokeByIndex(that, methodIndex, paramCount, params) +# a0 a1 a2 a3 + +NESTED(_NS_InvokeByIndex, FRAMESZ, ra) + PTR_SUBU sp, FRAMESZ + SETUP_GP64(GPOFF, _NS_InvokeByIndex) + + REG_S ra, RAOFF(sp) + REG_S a0, A0OFF(sp) + REG_S a1, A1OFF(sp) + REG_S a2, A2OFF(sp) + REG_S a3, A3OFF(sp) + REG_S s0, S0OFF(sp) + + # invoke_count_words(paramCount, params) + move a0, a2 + move a1, a3 + jal invoke_count_words + + # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + # nsXPTCVariant* s, uint32_t *reg) + + REG_L a1, A2OFF(sp) # a1 - paramCount + REG_L a2, A3OFF(sp) # a2 - params + + # save sp before we copy the params to the stack + move t0, sp + + # assume full size of 16 bytes per param to be safe + sll v0, 4 # 16 bytes * num params + PTR_SUBU sp, sp, v0 # make room + move a0, sp # a0 - param stack address + + # create temporary stack space to write int and fp regs + PTR_SUBU sp, 64 # 64 = 8 regs of 8 bytes + move a3, sp + + # save the old sp and save the arg stack + PTR_SUBU sp, sp, 16 + REG_S t0, 0(sp) + REG_S a0, 8(sp) + + # copy the param into the stack areas + jal invoke_copy_to_stack + + REG_L t3, 8(sp) # get previous a0 + REG_L sp, 0(sp) # get orig sp back + + REG_L a0, A0OFF(sp) # a0 - that + REG_L a1, A1OFF(sp) # a1 - methodIndex + + # t1 = methodIndex * pow(2, PTRLOG) + # (use shift instead of mult) + sll t1, a1, PTRLOG + + # calculate the function we need to jump to, + # which must then be saved in t9 + PTR_L t9, 0(a0) + PTR_ADDU t9, t9, t1 + PTR_L t9, (t9) + + # get register save area from invoke_copy_to_stack + PTR_SUBU t1, t3, 64 + + # a1..a7 and f13..f19 should now be set to what + # invoke_copy_to_stack told us. skip a0 and f12 + # because that's the "this" pointer + + REG_L a1, 0(t1) + REG_L a2, 8(t1) + REG_L a3, 16(t1) + REG_L a4, 24(t1) + REG_L a5, 32(t1) + REG_L a6, 40(t1) + REG_L a7, 48(t1) + + l.d $f13, 0(t1) + l.d $f14, 8(t1) + l.d $f15, 16(t1) + l.d $f16, 24(t1) + l.d $f17, 32(t1) + l.d $f18, 40(t1) + l.d $f19, 48(t1) + + # save away our stack pointer and create + # the stack pointer for the function + move s0, sp + move sp, t3 + + jalr t9 + + move sp, s0 + + RESTORE_GP64 + REG_L ra, RAOFF(sp) + REG_L s0, S0OFF(sp) + PTR_ADDU sp, FRAMESZ + j ra +.end _NS_InvokeByIndex diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s new file mode 100644 index 000000000..6fa9a86ba --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s @@ -0,0 +1,131 @@ + .LEVEL 1.1 +framesz .EQU 128 + +; XPTC_InvokeByIndex(nsISuppots* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params); + +; g++ need to compile everything with -fvtable-thunks ! + + .SPACE $TEXT$,SORT=8 + .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24 +XPTC_InvokeByIndex + .PROC + .CALLINFO CALLER,FRAME=72,ENTRY_GR=%r3,SAVE_RP,SAVE_SP,ARGS_SAVED,ALLOCA_FRAME + + ; frame marker takes 48 bytes, + ; register spill area takes 8 bytes, + ; local stack area takes 72 bytes result in 128 bytes total + + .ENTRY + STW %rp,-20(%sp) + STW,MA %r3,128(%sp) + + LDO -framesz(%r30),%r28 + STW %r28,-4(%r30) ; save previous sp + STW %r19,-32(%r30) + + STW %r26,-36-framesz(%r30) ; save argument registers in + STW %r25,-40-framesz(%r30) ; in PREVIOUS frame + STW %r24,-44-framesz(%r30) ; + STW %r23,-48-framesz(%r30) ; + + B,L .+8,%r2 + ADDIL L'invoke_count_bytes-$PIC_pcrel$1+4,%r2,%r1 + LDO R'invoke_count_bytes-$PIC_pcrel$2+8(%r1),%r1 +$PIC_pcrel$1 + LDSID (%r1),%r31 +$PIC_pcrel$2 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28 + BE,L 0(%sr0,%r1),%r31 + COPY %r31,%r2 + + CMPIB,>= 0,%r28, .+76 + COPY %r30,%r3 ; copy stack ptr to saved stack ptr + ADD %r30,%r28,%r30 ; extend stack frame + LDW -4(%r3),%r28 ; move frame + STW %r28,-4(%r30) + LDW -8(%r3),%r28 + STW %r28,-8(%r30) + LDW -12(%r3),%r28 + STW %r28,-12(%r30) + LDW -16(%r3),%r28 + STW %r28,-16(%r30) + LDW -20(%r3),%r28 + STW %r28,-20(%r30) + LDW -24(%r3),%r28 + STW %r28,-24(%r30) + LDW -28(%r3),%r28 + STW %r28,-28(%r30) + LDW -32(%r3),%r28 + STW %r28,-32(%r30) + + LDO -40(%r30),%r26 ; load copy address + LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments + LDW -48-framesz(%r3),%r24 ; + + LDW -32(%r30),%r19 ; shared lib call destroys r19; reload + B,L .+8,%r2 + ADDIL L'invoke_copy_to_stack-$PIC_pcrel$3+4,%r2,%r1 + LDO R'invoke_copy_to_stack-$PIC_pcrel$4+8(%r1),%r1 +$PIC_pcrel$3 + LDSID (%r1),%r31 +$PIC_pcrel$4 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26 + BE,L 0(%sr0,%r1),%r31 + COPY %r31,%r2 + + LDO -48(%r30),%r20 + EXTRW,U,= %r28,31,1,%r22 + FLDD 0(%r20),%fr7 ; load double arg 1 + EXTRW,U,= %r28,30,1,%r22 + FLDW 8(%r20),%fr5L ; load float arg 1 + EXTRW,U,= %r28,29,1,%r22 + FLDW 4(%r20),%fr6L ; load float arg 2 + EXTRW,U,= %r28,28,1,%r22 + FLDW 0(%r20),%fr7L ; load float arg 3 + + LDW -36-framesz(%r3),%r26 ; load ptr to 'that' + LDW -40(%r30),%r25 ; load the rest of dispatch argument registers + LDW -44(%r30),%r24 + LDW -48(%r30),%r23 + + LDW -36-framesz(%r3),%r20 ; load vtable addr + LDW -40-framesz(%r3),%r28 ; load index + LDW 0(%r20),%r20 ; follow vtable + LDO 16(%r20),%r20 ; offset vtable by 16 bytes (g++: 8, aCC: 16) + SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry + LDW 0(%r28),%r22 ; load vtable entry + + B,L .+8,%r2 + ADDIL L'$$dyncall_external-$PIC_pcrel$5+4,%r2,%r1 + LDO R'$$dyncall_external-$PIC_pcrel$6+8(%r1),%r1 +$PIC_pcrel$5 + LDSID (%r1),%r31 +$PIC_pcrel$6 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR +;in=22-26;out=28; + BE,L 0(%sr0,%r1),%r31 + COPY %r31,%r2 + + LDW -32(%r30),%r19 + COPY %r3,%r30 ; restore saved stack ptr + + LDW -148(%sp),%rp + BVE (%rp) + .EXIT + LDW,MB -128(%sp),%r3 + + .PROCEND ;in=23,24,25,26; + + .ALIGN 8 + .SPACE $TEXT$ + .SUBSPA $CODE$ + .IMPORT $$dyncall_external,MILLICODE + .IMPORT invoke_count_bytes,CODE + .IMPORT invoke_copy_to_stack,CODE + .EXPORT XPTC_InvokeByIndex,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR,LONG_RETURN + .END + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s new file mode 100644 index 000000000..7a207addf --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s @@ -0,0 +1,108 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .LEVEL 1.1 + .text + .align 4 + +framesz: + .equ 128 + +.globl NS_InvokeByIndex + .type NS_InvokeByIndex, @function + + +NS_InvokeByIndex: + .PROC + .CALLINFO FRAME=72, CALLER,SAVE_RP, SAVE_SP, ENTRY_GR=3 + .ENTRY + +; frame marker takes 48 bytes, +; register spill area takes 8 bytes, +; local stack area takes 72 bytes result in 128 bytes total + + STW %rp,-20(%sp) + STW,MA %r3,128(%sp) + + LDO -framesz(%r30),%r28 + STW %r28,-4(%r30) ; save previous sp + STW %r19,-32(%r30) + + STW %r26,-36-framesz(%r30) ; save argument registers in + STW %r25,-40-framesz(%r30) ; in PREVIOUS frame + STW %r24,-44-framesz(%r30) ; + STW %r23,-48-framesz(%r30) ; + + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28 + BL invoke_count_bytes,%r31 + COPY %r31,%r2 + + CMPIB,>= 0,%r28, .+76 + COPY %r30,%r3 ; copy stack ptr to saved stack ptr + ADD %r30,%r28,%r30 ; extend stack frame + LDW -4(%r3),%r28 ; move frame + STW %r28,-4(%r30) + LDW -8(%r3),%r28 + STW %r28,-8(%r30) + LDW -12(%r3),%r28 + STW %r28,-12(%r30) + LDW -16(%r3),%r28 + STW %r28,-16(%r30) + LDW -20(%r3),%r28 + STW %r28,-20(%r30) + LDW -24(%r3),%r28 + STW %r28,-24(%r30) + LDW -28(%r3),%r28 + STW %r28,-28(%r30) + LDW -32(%r3),%r28 + STW %r28,-32(%r30) + + LDO -40(%r30),%r26 ; load copy address + LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments + LDW -48-framesz(%r3),%r24 ; + + LDW -32(%r30),%r19 ; shared lib call destroys r19; reload + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26 + BL invoke_copy_to_stack,%r31 + COPY %r31,%r2 + + LDO -48(%r30),%r20 + EXTRW,U,= %r28,31,1,%r22 + FLDD 0(%r20),%fr7 ; load double arg 1 + EXTRW,U,= %r28,30,1,%r22 + FLDW 8(%r20),%fr5L ; load float arg 1 + EXTRW,U,= %r28,29,1,%r22 + FLDW 4(%r20),%fr6L ; load float arg 2 + EXTRW,U,= %r28,28,1,%r22 + FLDW 0(%r20),%fr7L ; load float arg 3 + + LDW -36-framesz(%r3),%r26 ; load ptr to 'that' + LDW -40(%r30),%r25 ; load the rest of dispatch argument registers + LDW -44(%r30),%r24 + LDW -48(%r30),%r23 + + LDW -36-framesz(%r3),%r20 ; load vtable addr + LDW -40-framesz(%r3),%r28 ; load index + LDW 0(%r20),%r20 ; follow vtable + SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry + LDW 0(%r28),%r22 ; load vtable entry + + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=22-26;out=28; + BL $$dyncall,%r31 + COPY %r31,%r2 + + LDW -32(%r30),%r19 + COPY %r3,%r30 ; restore saved stack ptr + + LDW -148(%sp),%rp + LDWM -128(%sp),%r3 + BV,N (%rp) + NOP + .EXIT + .PROCEND ;in=23,24,25,26; + .SIZE NS_InvokeByIndex, .-NS_InvokeByIndex + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S new file mode 100644 index 000000000..37211c885 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S @@ -0,0 +1,167 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set r1,1; .set r2,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + +# The ABI defines a fixed stack frame area of 4 doublewords (ELFv2) +# or 6 doublewords (ELFv1); the last of these doublewords is used +# as TOC pointer save area. The fixed area is followed by a parameter +# save area of 8 doublewords (used for vararg routines), followed +# by space for parameters passed on the stack. +# +# We set STACK_TOC to the offset of the TOC pointer save area, and +# STACK_PARAMS to the offset of the first on-stack parameter. + +#if _CALL_ELF == 2 +#define STACK_TOC 24 +#define STACK_PARAMS 96 +#else +#define STACK_TOC 40 +#define STACK_PARAMS 112 +#endif + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +#if _CALL_ELF == 2 + .section ".text" + .type NS_InvokeByIndex,@function + .globl NS_InvokeByIndex + .align 2 +NS_InvokeByIndex: +0: addis 2,12,(.TOC.-0b)@ha + addi 2,2,(.TOC.-0b)@l + .localentry NS_InvokeByIndex,.-NS_InvokeByIndex +#else + .section ".toc","aw" + .section ".text" + .align 2 + .globl NS_InvokeByIndex + .section ".opd","aw" + .align 3 +NS_InvokeByIndex: + .quad .NS_InvokeByIndex,.TOC.@tocbase + .previous + .type NS_InvokeByIndex,@function +.NS_InvokeByIndex: +#endif + mflr 0 + std 0,16(r1) + + std r29,-24(r1) + std r30,-16(r1) + std r31,-8(r1) + + mr r29,r3 # Save 'that' in r29 + mr r30,r4 # Save 'methodIndex' in r30 + mr r31,r1 # Save old frame + + # Allocate stack frame with space for params. Since at least the + # first 7 parameters (not including 'that') will be in registers, + # we don't actually need stack space for those. We must ensure + # that the stack remains 16-byte aligned. + # + # | (fixed area + | | 7 GP | 13 FP | 3 NV | + # | param. save) |(params)........| regs | regs | regs | + # (r1)......(+STACK_PARAMS)... (-23*8).(-16*8).(-3*8)..(r31) + + # +stack frame, -unused stack params, +regs storage, +1 for alignment + addi r7,r5,((STACK_PARAMS/8)-7+7+13+3+1) + rldicr r7,r7,3,59 # multiply by 8 and mask with ~15 + neg r7,r7 + stdux r1,r1,r7 + + + # Call invoke_copy_to_stack(uint64_t* gpregs, double* fpregs, + # uint32_t paramCount, nsXPTCVariant* s, + # uint64_t* d)) + + # r5, r6 are passed through intact (paramCount, params) + # r7 (d) has to be r1+STACK_PARAMS + # -- where parameters are passed on the stack. + # r3, r4 are above that, easier to address from r31 than from r1 + + subi r3,r31,(23*8) # r3 --> GPRS + subi r4,r31,(16*8) # r4 --> FPRS + addi r7,r1,STACK_PARAMS # r7 --> params + bl invoke_copy_to_stack + nop + + # Set up to invoke function + + ld r9,0(r29) # vtable (r29 is 'that') + mr r3,r29 # self is first arg, obviously + + sldi r30,r30,3 # Find function descriptor + add r9,r9,r30 + ld r12,0(r9) + + std r2,STACK_TOC(r1) # Save r2 (TOC pointer) + +#if _CALL_ELF == 2 + mtctr r12 +#else + ld r0,0(r12) # Actual address from fd. + mtctr 0 + ld r11,16(r12) # Environment pointer from fd. + ld r2,8(r12) # TOC pointer from fd. +#endif + + # Load FP and GP registers as required + ld r4, -(23*8)(r31) + ld r5, -(22*8)(r31) + ld r6, -(21*8)(r31) + ld r7, -(20*8)(r31) + ld r8, -(19*8)(r31) + ld r9, -(18*8)(r31) + ld r10, -(17*8)(r31) + + lfd f1, -(16*8)(r31) + lfd f2, -(15*8)(r31) + lfd f3, -(14*8)(r31) + lfd f4, -(13*8)(r31) + lfd f5, -(12*8)(r31) + lfd f6, -(11*8)(r31) + lfd f7, -(10*8)(r31) + lfd f8, -(9*8)(r31) + lfd f9, -(8*8)(r31) + lfd f10, -(7*8)(r31) + lfd f11, -(6*8)(r31) + lfd f12, -(5*8)(r31) + lfd f13, -(4*8)(r31) + + bctrl # Do it + + ld r2,STACK_TOC(r1) # Load our own TOC pointer + ld r1,0(r1) # Revert stack frame + ld 0,16(r1) # Reload lr + ld 29,-24(r1) # Restore NVGPRS + ld 30,-16(r1) + ld 31,-8(r1) + mtlr 0 + blr + +#if _CALL_ELF == 2 + .size NS_InvokeByIndex,.-NS_InvokeByIndex +#else + .size NS_InvokeByIndex,.-.NS_InvokeByIndex +#endif + + # Magic indicating no need for an executable stack + .section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s new file mode 100644 index 000000000..eb6b6661d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s @@ -0,0 +1,129 @@ +# +# -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +.set BO_IF,12 +.set CR0_EQ,2 + + + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex" + + +# .text section + + .csect H.10.NO_SYMBOL{PR} + .globl .NS_InvokeByIndex + .globl NS_InvokeByIndex{DS} + .extern .invoke_copy_to_stack + .extern ._ptrgl{PR} + + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.NS_InvokeByIndex: + mflr r0 + stw r31,-4(sp) +# +# save off the incoming values in the caller's parameter area +# + stw r3,24(sp) # that + stw r4,28(sp) # methodIndex + stw r5,32(sp) # paramCount + stw r6,36(sp) # params + stw r0,8(sp) + stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers + +# prepare args for 'invoke_copy_to_stack' call +# + lwz r4,168(sp) # paramCount + lwz r5,172(sp) # params + mr r6,sp # fprData + slwi r3,r4,3 # number of bytes of stack required + # at most 8*paramCount + addi r3,r3,28 # linkage area + mr r31,sp # save original stack top + subfc sp,r3,sp # bump the stack + addi r3,sp,28 # parameter pointer excludes linkage area size + 'this' + + bl .invoke_copy_to_stack + nop + + lfd f1,0(r31) # Restore floating point registers + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + lwz r3,160(r31) # that + lwz r4,0(r3) # get vTable from 'that' + lwz r5,164(r31) # methodIndex + slwi r5,r5,3 # methodIndex * 8 + addi r5,r5,8 # step over junk at start of vTable ! + lwzx r11,r5,r4 # get function pointer + + addi r5,r5,4 # We need to manually adjust the 'that' pointer, this is CFRONT based + lwzx r5,r4,r5 # offset = r4(vtable) + r5(methodIndex offset) - 4 + add r3,r5,r3 # adjust 'that' r3 = r3 + r5 + + lwz r4,28(sp) + lwz r5,32(sp) + lwz r6,36(sp) + lwz r7,40(sp) + lwz r8,44(sp) + lwz r9,48(sp) + lwz r10,52(sp) + + bl ._ptrgl{PR} + nop + + mr sp,r31 + lwz r0,144(sp) + addi sp,sp,136 + mtlr r0 + lwz r31,-4(sp) + blr + + +# .data section + + .toc # 0x00000038 +T.18.NS_InvokeByIndex: + .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS} + + .csect NS_InvokeByIndex{DS} + .long .NS_InvokeByIndex # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0008" + .long 0x00000000 # "\0\0\0\0" +# End csect NS_InvokeByIndex{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s new file mode 100644 index 000000000..722583de5 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s @@ -0,0 +1,128 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +.set BO_IF,12 +.set CR0_EQ,2 + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex" + + +# .text section + + .csect H.10.NO_SYMBOL{PR} + .globl .NS_InvokeByIndex + .globl NS_InvokeByIndex{DS} + .extern .invoke_copy_to_stack + .extern ._ptrgl{PR} + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.NS_InvokeByIndex: + mflr r0 + std r31,-8(sp) +# +# save off the incoming values in the caller's parameter area +# + std r3,48(sp) # that + std r4,56(sp) # methodIndex + std r5,64(sp) # paramCount + std r6,72(sp) # params + std r0,16(sp) + stdu sp,-168(sp) # 2*24=48 for linkage area, + # 8*13=104 for fprData area + # 16 for saved registers + +# prepare args for 'invoke_copy_to_stack' call +# + ld r4,232(sp) # paramCount (168+8+56) + ld r5,240(sp) # params + mr r6,sp # fprData + sldi r3,r4,3 # number of bytes of stack required + # is at most numParams*8 + addi r3,r3,56 # linkage area (48) + this (8) + mr r31,sp # save original stack top + subfc sp,r3,sp # bump the stack + addi r3,sp,56 # parameter pointer excludes linkage area + # size + 'this' + + bl .invoke_copy_to_stack + nop + + lfd f1,0(r31) # Restore floating point registers + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + ld r3,216(r31) # that (168+48) + ld r4,0(r3) # get vTable from 'that' + ld r5,224(r31) # methodIndex (168+56) + sldi r5,r5,3 # methodIndex * 8 + # No junk at the start of 64bit vtable !!! + ldx r11,r5,r4 # get function pointer (this jumps + # either to the function if no adjustment + # is needed (displacement = 0), or it + # jumps to the thunk code, which will jump + # to the function at the end) + + # No adjustment of the that pointer in 64bit mode, this is done + # by the thunk code + + ld r4,56(sp) + ld r5,64(sp) + ld r6,72(sp) + ld r7,80(sp) + ld r8,88(sp) + ld r9,96(sp) + ld r10,104(sp) + + bl ._ptrgl{PR} + nop + + mr sp,r31 + ld r0,184(sp) # 168+16 + addi sp,sp,168 + mtlr r0 + ld r31,-8(sp) + blr + +# .data section + + .toc # 0x00000038 +T.18.NS_InvokeByIndex: + .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS} + + .csect NS_InvokeByIndex{DS} + .llong .NS_InvokeByIndex # "\0\0\0\0" + .llong TOC{TC0} # "\0\0\0008" + .llong 0x00000000 # "\0\0\0\0" +# End csect NS_InvokeByIndex{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s new file mode 100644 index 000000000..414a6536f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s @@ -0,0 +1,124 @@ +# +# -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +.set BO_IF,12 +.set CR0_EQ,2 + + + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex" + + +# .text section + + .csect H.10.NO_SYMBOL{PR} + .globl .NS_InvokeByIndex + .globl NS_InvokeByIndex{DS} + .extern .invoke_copy_to_stack + .extern ._ptrgl{PR} + + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.NS_InvokeByIndex: + mflr r0 + stw r31,-4(sp) +# +# save off the incoming values in the caller's parameter area +# + stw r3,24(sp) # that + stw r4,28(sp) # methodIndex + stw r5,32(sp) # paramCount + stw r6,36(sp) # params + stw r0,8(sp) + stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers + +# prepare args for 'invoke_copy_to_stack' call +# + lwz r4,168(sp) # paramCount + lwz r5,172(sp) # params + mr r6,sp # fprData + slwi r3,r4,3 # number of bytes of stack required + # at most 8*paramCount + addi r3,r3,28 # linkage area + mr r31,sp # save original stack top + subfc sp,r3,sp # bump the stack + addi r3,sp,28 # parameter pointer excludes linkage area size + 'this' + + bl .invoke_copy_to_stack + nop + + lfd f1,0(r31) # Restore floating point registers + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + lwz r3,160(r31) # that + lwz r4,0(r3) # get vTable from 'that' + lwz r5,164(r31) # methodIndex + slwi r5,r5,2 # methodIndex * 4 + lwzx r11,r5,r4 # get function pointer + + lwz r4,28(sp) + lwz r5,32(sp) + lwz r6,36(sp) + lwz r7,40(sp) + lwz r8,44(sp) + lwz r9,48(sp) + lwz r10,52(sp) + + bl ._ptrgl{PR} + nop + + mr sp,r31 + lwz r0,144(sp) + addi sp,sp,136 + mtlr r0 + lwz r31,-4(sp) + blr + + +# .data section + + .toc # 0x00000038 +T.18.NS_InvokeByIndex: + .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS} + + .csect NS_InvokeByIndex{DS} + .long .NS_InvokeByIndex # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0008" + .long 0x00000000 # "\0\0\0\0" +# End csect NS_InvokeByIndex{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S new file mode 100644 index 000000000..e87382286 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S @@ -0,0 +1,98 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl NS_InvokeByIndex + .type NS_InvokeByIndex,@function + +// +// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params) +// + +NS_InvokeByIndex: + stwu sp,-32(sp) // setup standard stack frame + mflr r0 // save LR + stw r3,8(sp) // r3 <= that + stw r4,12(sp) // r4 <= methodIndex + stw r30,16(sp) + stw r31,20(sp) + + stw r0,36(sp) // store LR backchain + mr r31,sp + + rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f + addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96 + lwz r9,0(sp) // r9 = backchain + neg r0,r0 + stwux r9,sp,r0 // reserve stack space and save SP backchain + + addi r3,sp,8 // r3 <= args + mr r4,r5 // r4 <= paramCount + mr r5,r6 // r5 <= params + add r6,r3,r10 // r6 <= gpregs ( == args + r10 ) + mr r30,r6 // store in r30 for use later... +#ifndef __NO_FPRS__ + addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 ) +#else + li r7, 0 +#endif + + bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs) +#ifndef __NO_FPRS__ + lfd f1,32(r30) // load FP registers with method parameters + lfd f2,40(r30) + lfd f3,48(r30) + lfd f4,56(r30) + lfd f5,64(r30) + lfd f6,72(r30) + lfd f7,80(r30) + lfd f8,88(r30) +#endif + lwz r3,8(r31) // r3 <= that + lwz r4,12(r31) // r4 <= methodIndex + lwz r5,0(r3) // r5 <= vtable ( == *that ) + slwi r4,r4,2 // convert to offset ( *= 4 ) + lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset ) + + lwz r4,4(r30) // load GP regs with method parameters + lwz r5,8(r30) + lwz r6,12(r30) + lwz r7,16(r30) + lwz r8,20(r30) + lwz r9,24(r30) + lwz r10,28(r30) + + mtlr r0 // copy methodpointer to LR + blrl // call method + + lwz r30,16(r31) // restore r30 & r31 + lwz r31,20(r31) + + lwz r11,0(sp) // clean up the stack + lwz r0,4(r11) + mtlr r0 + mr sp,r11 + blr + +/* Magic indicating no need for an executable stack */ +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s new file mode 100644 index 000000000..33650f399 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s @@ -0,0 +1,95 @@ +# -*- Mode: Asm -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl XPTC_InvokeByIndex + .type XPTC_InvokeByIndex,@function + +# +# XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +XPTC_InvokeByIndex: + stwu sp,-32(sp) # setup standard stack frame + mflr r0 # save LR + stw r3,8(sp) # r3 <= that + stw r4,12(sp) # r4 <= methodIndex + stw r30,16(sp) + stw r31,20(sp) + + stw r0,36(sp) # store LR backchain + mr r31,sp + + rlwinm r10,r5,3,0,27 # r10 = (ParamCount * 2 * 4) & ~0x0f + addi r0,r10,96 # reserve stack for GPR and FPR register save area r0 = r10 + 96 + lwz r9,0(sp) # r9 = backchain + neg r0,r0 + stwux r9,sp,r0 # reserve stack sapce and save SP backchain + + addi r3,sp,8 # r3 <= args + mr r4,r5 # r4 <= paramCount + mr r5,r6 # r5 <= params + add r6,r3,r10 # r6 <= gpregs ( == args + r10 ) + mr r30,r6 # store in r30 for use later... + addi r7,r6,32 # r7 <= fpregs ( == gpregs + 32 ) + + bl invoke_copy_to_stack@local # (args, paramCount, params, gpregs, fpregs) + + lfd f1,32(r30) # load FP registers with method parameters + lfd f2,40(r30) + lfd f3,48(r30) + lfd f4,56(r30) + lfd f5,64(r30) + lfd f6,72(r30) + lfd f7,80(r30) + lfd f8,88(r30) + + lwz r3,8(r31) # r3 <= that + lwz r4,12(r31) # r4 <= methodIndex + lwz r5,0(r3) # r5 <= vtable ( == *that ) + slwi r4,r4,3 # convert to offset ( *= 8 ) + addi r4,r4,8 # skip first two vtable entries + add r4,r4,r5 + lhz r0,0(r4) # virtual base offset + extsh r0,r0 + add r3,r3,r0 + lwz r0,4(r4) # r0 <= methodpointer ( == vtable + offset ) + + lwz r4,4(r30) # load GP regs with method parameters + lwz r5,8(r30) + lwz r6,12(r30) + lwz r7,16(r30) + lwz r8,20(r30) + lwz r9,24(r30) + lwz r10,28(r30) + + mtlr r0 # copy methodpointer to LR + blrl # call method + + lwz r30,16(r31) # restore r30 & r31 + lwz r31,20(r31) + + lwz r11,0(sp) # clean up the stack + lwz r0,4(r11) + mtlr r0 + mr sp,r11 + blr diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S new file mode 100644 index 000000000..f02c0b220 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S @@ -0,0 +1,94 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl NS_InvokeByIndex + .type NS_InvokeByIndex,@function + +// +// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params) +// + +NS_InvokeByIndex: + stwu sp,-32(sp) // setup standard stack frame + mflr r0 // save LR + stw r3,8(sp) // r3 <= that + stw r4,12(sp) // r4 <= methodIndex + stw r30,16(sp) + stw r31,20(sp) + + stw r0,36(sp) // store LR backchain + mr r31,sp + + rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f + addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96 + lwz r9,0(sp) // r9 = backchain + neg r0,r0 + stwux r9,sp,r0 // reserve stack space and save SP backchain + + addi r3,sp,8 // r3 <= args + mr r4,r5 // r4 <= paramCount + mr r5,r6 // r5 <= params + add r6,r3,r10 // r6 <= gpregs ( == args + r10 ) + mr r30,r6 // store in r30 for use later... + addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 ) + + bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs) + + lfd f1,32(r30) // load FP registers with method parameters + lfd f2,40(r30) + lfd f3,48(r30) + lfd f4,56(r30) + lfd f5,64(r30) + lfd f6,72(r30) + lfd f7,80(r30) + lfd f8,88(r30) + + lwz r3,8(r31) // r3 <= that + lwz r4,12(r31) // r4 <= methodIndex + lwz r5,0(r3) // r5 <= vtable ( == *that ) + slwi r4,r4,2 // convert to offset ( *= 4 ) + lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset ) + + lwz r4,4(r30) // load GP regs with method parameters + lwz r5,8(r30) + lwz r6,12(r30) + lwz r7,16(r30) + lwz r8,20(r30) + lwz r9,24(r30) + lwz r10,28(r30) + + mtlr r0 // copy methodpointer to LR + blrl // call method + + lwz r30,16(r31) // restore r30 & r31 + lwz r31,20(r31) + + lwz r11,0(sp) // clean up the stack + lwz r0,4(r11) + mtlr r0 + mr sp,r11 + blr + +// Magic indicating no need for an executable stack +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s new file mode 100644 index 000000000..1dc12b2b3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s @@ -0,0 +1,142 @@ +# +# -*- Mode: Asm -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# +# ** Assumed vtable layout (obtained by disassembling with gdb): +# ** 4 bytes per vtable entry, skip 0th and 1st entries, so the mapping +# ** from index to entry is (4 * index) + 8. +# + +.text + .align 2 +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.globl __NS_InvokeByIndex +__NS_InvokeByIndex: + mflr r0 + stw r31,-4(r1) +# +# save off the incoming values in the callers parameter area +# + stw r3,24(r1) ; that + stw r4,28(r1) ; methodIndex + stw r5,32(r1) ; paramCount + stw r6,36(r1) ; params + stw r0,8(r1) + stwu r1,-144(r1) ; 24 for linkage area, + ; 8*13 for fprData area, + ; 8 for saved registers, + ; 8 to keep stack 16-byte aligned + +# set up for and call 'invoke_count_words' to get new stack size +# + mr r3,r5 + mr r4,r6 + + stwu r1,-24(r1) + bl L_invoke_count_words$stub + lwz r1,0(r1) + +# prepare args for 'invoke_copy_to_stack' call +# + lwz r4,176(r1) ; paramCount + lwz r5,180(r1) ; params + mr r6,r1 ; fprData + slwi r3,r3,2 ; number of stack bytes required + addi r3,r3,28 ; linkage area + mr r31,r1 ; save original stack top + sub r1,r1,r3 ; bump the stack + clrrwi r1,r1,4 ; keep the stack 16-byte aligned + addi r3,r31,144 ; act like real alloca, so 0(sp) always + stw r3,0(r1) ; points back to previous stack frame + addi r3,r1,28 ; parameter pointer excludes linkage area size + 'this' + +# create "temporary" stack frame for _invoke_copy_to_stack to operate in. + stwu r1,-40(r1) + bl L_invoke_copy_to_stack$stub +# remove temporary stack frame. + lwz r1,0(r1) + + lfd f1,0(r31) + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + lwz r3,168(r31) ; that + lwz r4,0(r3) ; get vTable from 'that' + lwz r5,172(r31) ; methodIndex + slwi r5,r5,2 ; methodIndex * 4 + lwzx r12,r5,r4 ; get function pointer + + lwz r4,28(r1) + lwz r5,32(r1) + lwz r6,36(r1) + lwz r7,40(r1) + lwz r8,44(r1) + lwz r9,48(r1) + lwz r10,52(r1) + + mtlr r12 + blrl + + mr r1,r31 + lwz r0,152(r1) + addi r1,r1,144 + mtlr r0 + lwz r31,-4(r1) + + blr + +.picsymbol_stub +L_invoke_count_words$stub: + .indirect_symbol _invoke_count_words + mflr r0 + bcl 20,31,L1$pb +L1$pb: + mflr r11 + addis r11,r11,ha16(L1$lz-L1$pb) + mtlr r0 + lwz r12,lo16(L1$lz-L1$pb)(r11) + mtctr r12 + addi r11,r11,lo16(L1$lz-L1$pb) + bctr +.lazy_symbol_pointer +L1$lz: + .indirect_symbol _invoke_count_words + .long dyld_stub_binding_helper + + +.picsymbol_stub +L_invoke_copy_to_stack$stub: + .indirect_symbol _invoke_copy_to_stack + mflr r0 + bcl 20,31,L2$pb +L2$pb: + mflr r11 + addis r11,r11,ha16(L2$lz-L2$pb) + mtlr r0 + lwz r12,lo16(L2$lz-L2$pb)(r11) + mtctr r12 + addi r11,r11,lo16(L2$lz-L2$pb) + bctr +.lazy_symbol_pointer +L2$lz: + .indirect_symbol _invoke_copy_to_stack + .long dyld_stub_binding_helper + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s new file mode 100644 index 000000000..dfd6189f8 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s @@ -0,0 +1,86 @@ +/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + Platform specific code to invoke XPCOM methods on native objects + for sparcv9 Solaris. + + See the SPARC Compliance Definition (SCD) Chapter 3 + for more information about what is going on here, including + the use of BIAS (0x7ff). + The SCD is available from http://www.sparc.com/. +*/ + + .global NS_InvokeByIndex + .type NS_InvokeByIndex, #function + +/* + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +NS_InvokeByIndex: + save %sp,-(128 + 64),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 64 + sll %i2,4,%l0 ! assume the worst case + ! paramCount * 2 * 8 bytes + cmp %l0, 0 ! are there any args? If not, + be .invoke ! no need to copy args to stack + nop + + sub %sp,%l0,%sp ! create the additional stack space + add %sp,0x7ff+136,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params + +! +! load arguments from stack into the outgoing registers +! BIAS is 0x7ff (2047) +! + +! load the %o1..5 64bit (extended word) output registers registers + ldx [%sp + 0x7ff + 136],%o1 ! %i1 + ldx [%sp + 0x7ff + 144],%o2 ! %i2 + ldx [%sp + 0x7ff + 152],%o3 ! %i3 + ldx [%sp + 0x7ff + 160],%o4 ! %i4 + ldx [%sp + 0x7ff + 168],%o5 ! %i5 + +! load the even number double registers starting with %f2 + ldd [%sp + 0x7ff + 136],%f2 + ldd [%sp + 0x7ff + 144],%f4 + ldd [%sp + 0x7ff + 152],%f6 + ldd [%sp + 0x7ff + 160],%f8 + ldd [%sp + 0x7ff + 168],%f10 + ldd [%sp + 0x7ff + 176],%f12 + ldd [%sp + 0x7ff + 184],%f14 + ldd [%sp + 0x7ff + 192],%f16 + ldd [%sp + 0x7ff + 200],%f18 + ldd [%sp + 0x7ff + 208],%f20 + ldd [%sp + 0x7ff + 216],%f22 + ldd [%sp + 0x7ff + 224],%f24 + ldd [%sp + 0x7ff + 232],%f26 + ldd [%sp + 0x7ff + 240],%f28 + ldd [%sp + 0x7ff + 248],%f30 + +! +! calculate the target address from the vtable +! +.invoke: + sll %i1,3,%l0 ! index *= 8 +! add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes) + ldx [%i0],%l1 ! *that --> address of vtable + ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address + + jmpl %l0,%o7 ! call the routine + mov %i0,%o0 ! move 'this' pointer to out register + + mov %o0,%i0 ! propagate return value + ret + restore + + .size NS_InvokeByIndex, .-NS_InvokeByIndex diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s new file mode 100644 index 000000000..36196805e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Platform specific code to invoke XPCOM methods on native objects for + * Linux/Sparc with gcc 3 ABI. + */ + .global NS_InvokeByIndex +/* + * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params); + * + */ +NS_InvokeByIndex: + save %sp,-(64 + 16),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 16 + mov %i2,%o0 ! paramCount + call invoke_count_words ! returns the required stack size in %o0 + mov %i3,%o1 ! params + + sll %o0,2,%l0 ! number of bytes + sub %sp,%l0,%sp ! create the additional stack space + + mov %sp,%o0 ! pointer for copied args + add %o0,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params +! +! calculate the target address from the vtable +! + ld [%i0],%l1 ! *that --> vTable + sll %i1,2,%i1 ! multiply index by 4 + add %i1,%l1,%l1 ! l1 now points to vTable entry + ld [%l1],%l0 ! target address + +.L5: ld [%sp + 88],%o5 +.L4: ld [%sp + 84],%o4 +.L3: ld [%sp + 80],%o3 +.L2: ld [%sp + 76],%o2 +.L1: ld [%sp + 72],%o1 +.L0: + jmpl %l0,%o7 ! call the routine +! always have a 'this', from the incoming 'that' + mov %i0,%o0 + + mov %o0,%i0 ! propagate return value + ret + restore diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s new file mode 100644 index 000000000..893432a5e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + .global XPTC_InvokeByIndex +/* + XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +XPTC_InvokeByIndex: + save %sp,-(64 + 16),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 16 + mov %i2,%o0 ! paramCount + call invoke_count_words ! returns the required stack size in %o0 + mov %i3,%o1 ! params + + sll %o0,2,%l0 ! number of bytes + sub %sp,%l0,%sp ! create the additional stack space + + mov %sp,%o0 ! pointer for copied args + add %o0,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params +! +! calculate the target address from the vtable +! + add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?) + ld [%i0],%l1 ! *that --> vTable + sll %i1,3,%i1 + add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry + lduh [%l1],%l0 ! this adjustor + sll %l0,16,%l0 ! sign extend to 32 bits + sra %l0,16,%l0 + add %l0,%i0,%i0 ! adjust this + ld [%l1 + 4],%l0 ! target address + +.L5: ld [%sp + 88],%o5 +.L4: ld [%sp + 84],%o4 +.L3: ld [%sp + 80],%o3 +.L2: ld [%sp + 76],%o2 +.L1: ld [%sp + 72],%o1 +.L0: + jmpl %l0,%o7 ! call the routine +! always have a 'this', from the incoming 'that' + mov %i0,%o0 + + mov %o0,%i0 ! propagate return value + ret + restore diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s new file mode 100644 index 000000000..1ef695370 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + .global XPTC_InvokeByIndex +/* + XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +XPTC_InvokeByIndex: + save %sp,-(64 + 16),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 16 + mov %i2,%o0 ! paramCount + call invoke_count_words ! returns the required stack size in %o0 + mov %i3,%o1 ! params + + sll %o0,2,%l0 ! number of bytes + sub %sp,%l0,%sp ! create the additional stack space + + mov %sp,%o0 ! pointer for copied args + add %o0,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params +! +! calculate the target address from the vtable +! + add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?) + ld [%i0],%l1 ! *that --> vTable + sll %i1,3,%i1 + add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry + lduh [%l1],%l0 ! this adjustor + sll %l0,16,%l0 ! sign extend to 32 bits + sra %l0,16,%l0 + add %l0,%i0,%i0 ! adjust this + ld [%l1 + 4],%l0 ! target address + +.L5: ld [%sp + 88],%o5 +.L4: ld [%sp + 84],%o4 +.L3: ld [%sp + 80],%o3 +.L2: ld [%sp + 76],%o2 +.L1: ld [%sp + 72],%o1 +.L0: + jmpl %l0,%o7 ! call the routine +! always have a 'this', from the incoming 'that' + mov %i0,%o0 + + mov %o0,%i0 ! propagate return value + ret + restore diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s new file mode 100644 index 000000000..54adcd147 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Platform specific code to invoke XPCOM methods on native objects for + * solaris/sparc with gcc 3 ABI. + */ + .global NS_InvokeByIndex +/* + * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params); + */ +NS_InvokeByIndex: + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 + mov %i2,%o0 ! paramCount + call invoke_count_words ! returns the required stack size in %o0 + mov %i3,%o1 ! params + + sll %o0,2,%l0 ! number of bytes + sub %sp,%l0,%sp ! create the additional stack space + + mov %sp,%o0 ! pointer for copied args + add %o0,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params +! +! calculate the target address from the vtable +! + ld [%i0],%l1 ! *that --> vTable + sll %i1,2,%i1 ! multiply index by 4 + add %i1,%l1,%l1 ! l1 now points to vTable entry + ld [%l1],%l0 ! target address + +.L5: ld [%sp + 88],%o5 +.L4: ld [%sp + 84],%o4 +.L3: ld [%sp + 80],%o3 +.L2: ld [%sp + 76],%o2 +.L1: ld [%sp + 72],%o1 +.L0: + jmpl %l0,%o7 ! call the routine +! always have a 'this', from the incoming 'that' + mov %i0,%o0 + + mov %o0,%i0 ! propagate return value + ret + restore diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s new file mode 100644 index 000000000..013770392 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + + .global NS_InvokeByIndex + .type NS_InvokeByIndex, #function +/* + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +NS_InvokeByIndex: + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 + sll %i2,3,%l0 ! assume the worst case + ! paramCount * 2 * 4 bytes + cmp %l0, 0 ! are there any args? If not, + be .invoke ! no need to copy args to stack + + sub %sp,%l0,%sp ! create the additional stack space + add %sp,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params + +! +! load arguments from stack into the outgoing registers +! + ld [%sp + 72],%o1 + ld [%sp + 76],%o2 + ld [%sp + 80],%o3 + ld [%sp + 84],%o4 + ld [%sp + 88],%o5 + +! +! calculate the target address from the vtable +! +.invoke: + sll %i1,2,%l0 ! index *= 4 + add %l0,8,%l0 ! there are 2 extra entries in the vTable + ld [%i0],%l1 ! *that --> address of vtable + ld [%l0 + %l1],%l0 ! that->vtable[index * 4 + 8] --> address + + jmpl %l0,%o7 ! call the routine + mov %i0,%o0 ! move 'this' pointer to out register + + mov %o0,%i0 ! propagate return value + ret + restore + + .size NS_InvokeByIndex, .-NS_InvokeByIndex diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s new file mode 100644 index 000000000..34861abc0 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s @@ -0,0 +1,85 @@ +/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + Platform specific code to invoke XPCOM methods on native objects + for sparcv9 Solaris. + + See the SPARC Compliance Definition (SCD) Chapter 3 + for more information about what is going on here, including + the use of BIAS (0x7ff). + The SCD is available from http://www.sparc.com/. +*/ + + .global NS_InvokeByIndex + .type NS_InvokeByIndex, #function + +/* + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +NS_InvokeByIndex: + save %sp,-(128 + 64),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 64 + sll %i2,4,%l0 ! assume the worst case + ! paramCount * 2 * 8 bytes + cmp %l0, 0 ! are there any args? If not, + be .invoke ! no need to copy args to stack + + sub %sp,%l0,%sp ! create the additional stack space + add %sp,0x7ff+136,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params + +! +! load arguments from stack into the outgoing registers +! BIAS is 0x7ff (2047) +! + +! load the %o1..5 64bit (extended word) output registers registers + ldx [%sp + 0x7ff + 136],%o1 ! %i1 + ldx [%sp + 0x7ff + 144],%o2 ! %i2 + ldx [%sp + 0x7ff + 152],%o3 ! %i3 + ldx [%sp + 0x7ff + 160],%o4 ! %i4 + ldx [%sp + 0x7ff + 168],%o5 ! %i5 + +! load the even number double registers starting with %d2 + ldd [%sp + 0x7ff + 136],%d2 + ldd [%sp + 0x7ff + 144],%d4 + ldd [%sp + 0x7ff + 152],%d6 + ldd [%sp + 0x7ff + 160],%d8 + ldd [%sp + 0x7ff + 168],%d10 + ldd [%sp + 0x7ff + 176],%d12 + ldd [%sp + 0x7ff + 184],%d14 + ldd [%sp + 0x7ff + 192],%d16 + ldd [%sp + 0x7ff + 200],%d18 + ldd [%sp + 0x7ff + 208],%d20 + ldd [%sp + 0x7ff + 216],%d22 + ldd [%sp + 0x7ff + 224],%d24 + ldd [%sp + 0x7ff + 232],%d26 + ldd [%sp + 0x7ff + 240],%d28 + ldd [%sp + 0x7ff + 248],%d30 + +! +! calculate the target address from the vtable +! +.invoke: + sll %i1,3,%l0 ! index *= 8 + add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes) + ldx [%i0],%l1 ! *that --> address of vtable + ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address + + jmpl %l0,%o7 ! call the routine + mov %i0,%o0 ! move 'this' pointer to out register + + mov %o0,%i0 ! propagate return value + ret + restore + + .size NS_InvokeByIndex, .-NS_InvokeByIndex diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s new file mode 100644 index 000000000..af665a162 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s @@ -0,0 +1,55 @@ + .globl NS_InvokeByIndex + .type NS_InvokeByIndex, @function +NS_InvokeByIndex: + push %ebp + movl %esp,%ebp + push %ebx + call .CG0.66 +.CG0.66: + pop %ebx + addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx + push 20(%ebp) + push 16(%ebp) + push 12(%ebp) + push 8(%ebp) + / INLINE: invoke_by_index + + + + pushl %ebx + pushl %esi + movl %esp, %ebx + + pushl 0x14(%ebp) + pushl 0x10(%ebp) + call invoke_count_words + mov %ebx, %esp + + sall $0x2 , %eax + subl %eax, %esp + movl %esp, %esi + + pushl %esp + pushl 0x14(%ebp) + pushl 0x10(%ebp) + call invoke_copy_to_stack + movl %esi, %esp + + movl 0x8(%ebp), %ecx + pushl %ecx + movl (%ecx), %edx + movl 0xc(%ebp), %eax + movl 0x8(%edx, %eax, 4), %edx + + call *%edx + mov %ebx, %esp + popl %esi + popl %ebx + / INLINE_END + addl $16,%esp + pop %ebx + movl %ebp,%esp + pop %ebp + ret + .size NS_InvokeByIndex, . - NS_InvokeByIndex + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp new file mode 100644 index 000000000..04407db39 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp @@ -0,0 +1,16 @@ +/* -*- Mode: C -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#if defined(__i386__) +#include "xptcinvoke_gcc_x86_unix.cpp" +#elif defined(__x86_64__) +#include "xptcinvoke_x86_64_unix.cpp" +#elif defined(__ppc__) +#include "xptcinvoke_ppc_rhapsody.cpp" +#elif defined(__arm__) +#include "xptcinvoke_arm.cpp" +#else +#error unknown cpu architecture +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp new file mode 100644 index 000000000..d4a8a12fb --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp @@ -0,0 +1,97 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" +#include "xptc_gcc_x86_unix.h" + +extern "C" { +static void ATTRIBUTE_USED __attribute__ ((regparm(3))) +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d) +{ + for(uint32_t i = paramCount; i >0; i--, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + + switch(s->type) + { + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + default : *((void**)d) = s->val.p; break; + } + } +} +} // extern "C" + +/* + EXPORT_XPCOM_API(nsresult) + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + + Each param takes at most two 4-byte words. + It doesn't matter if we push too many words, and calculating the exact + amount takes time. + + that = ebp + 0x08 + methodIndex = ebp + 0x0c + paramCount = ebp + 0x10 + params = ebp + 0x14 + +*/ + +__asm__ ( + ".text\n\t" +/* alignment here seems unimportant here; this was 16, now it's 2 which + is what xptcstubs uses. */ + ".align 2\n\t" + ".globl " SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t" +#ifndef XP_MACOSX + ".type " SYMBOL_UNDERSCORE "NS_InvokeByIndex,@function\n" +#endif + SYMBOL_UNDERSCORE "NS_InvokeByIndex:\n\t" + "pushl %ebp\n\t" + "movl %esp, %ebp\n\t" + "movl 0x10(%ebp), %eax\n\t" + "leal 0(,%eax,8),%edx\n\t" + + /* set up call frame for method. */ + "subl %edx, %esp\n\t" /* make room for params. */ +/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size. + * This is to avoid protection faults where SSE+ alignment of stack pointer + * is assumed and required, e.g. by GCC4's -ftree-vectorize option. + */ + "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */ +/* $esp should be aligned to a 16-byte boundary here (note we include an + * additional 4 bytes in a later push instruction). This will ensure $ebp + * in the function called below is aligned to a 0x8 boundary. SSE instructions + * like movapd/movdqa expect memory operand to be aligned on a 16-byte + * boundary. The GCC compiler will generate the memory operand using $ebp + * with an 8-byte offset. + */ + "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */ + "movl %esp, %ecx\n\t" /* ecx = d */ + "movl 8(%ebp), %edx\n\t" /* edx = this */ + "pushl %edx\n\t" /* push this. esp % 16 == 0 */ + + "movl 0x14(%ebp), %edx\n\t" + "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t" + "movl 0x08(%ebp), %ecx\n\t" /* 'that' */ + "movl (%ecx), %edx\n\t" + "movl 0x0c(%ebp), %eax\n\t" /* function index */ + "leal (%edx,%eax,4), %edx\n\t" + "call *(%edx)\n\t" + "movl %ebp, %esp\n\t" + "popl %ebp\n\t" + "ret\n" +#ifndef XP_MACOSX + ".size " SYMBOL_UNDERSCORE "NS_InvokeByIndex, . -" SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t" +#endif +); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp new file mode 100644 index 000000000..1500f3175 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp @@ -0,0 +1,132 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#include <iostream.h> + +// "This code is for IA64 only" + + +/* invoke_copy_to_stack() will copy from variant array 's' to + * the stack argument area 'mloc', the integer register area 'iloc', and + * the float register area 'floc'. + * + */ +extern "C" void +invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc, + const uint32_t paramCount, nsXPTCVariant* s) +{ + uint64_t* dest = mloc; + uint32_t len = paramCount; + nsXPTCVariant* source = s; + + uint32_t indx; + uint32_t endlen; + endlen = (len > 7) ? 7 : len; + /* handle the memory arguments */ + for (indx = 7; indx < len; ++indx) + { + if (source[indx].IsPtrData()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].ptr; +#endif + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; +#else + { + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].val.p; + } +#endif + } + ++dest; + } + /* process register arguments */ + dest = iloc; + for (indx = 0; indx < endlen; ++indx) + { + if (source[indx].IsPtrData()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].ptr; +#endif + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : + *((double*) (floc++)) = (double) source[indx].val.f; + break; + case nsXPTType::T_DOUBLE: + *((double*) (floc++)) = source[indx].val.d; + break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; +#else + { + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].val.p; + } +#endif + } + ++dest; + } + +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp new file mode 100644 index 000000000..c2a4dd088 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp @@ -0,0 +1,100 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#include <stdint.h> + +// "This code is for IA64 only" + + +/* invoke_copy_to_stack() will copy from variant array 's' to + * the stack argument area 'mloc', the integer register area 'iloc', and + * the float register area 'floc'. + * + */ +extern "C" void +invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc, + const uint32_t paramCount, nsXPTCVariant* s) +{ + uint64_t* dest = mloc; + uint32_t len = paramCount; + nsXPTCVariant* source = s; + + uint32_t indx; + uint32_t endlen; + endlen = (len > 7) ? 7 : len; + /* handle the memory arguments */ + for (indx = 7; indx < len; ++indx) + { + if (source[indx].IsPtrData()) + { + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; + } + ++dest; + } + /* process register arguments */ + dest = iloc; + for (indx = 0; indx < endlen; ++indx) + { + if (source[indx].IsPtrData()) + { + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : + *((double*) (floc++)) = (double) source[indx].val.f; + break; + case nsXPTType::T_DOUBLE: + *((double*) (floc++)) = source[indx].val.d; + break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; + } + ++dest; + } + +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp new file mode 100644 index 000000000..dc111e435 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +__asm__("invoke_copy_to_stack") __attribute__((used)); + +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *d = (uint64_t)s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break; + case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break; + case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break; + case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break; + case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break; + case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break; + case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break; + case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // convert floats to doubles if they are to be passed + // via registers so we can just deal with doubles later + union { uint64_t u64; double d; } t; + t.d = (double)s->val.f; + *d = t.u64; + } + else + // otherwise copy to stack normally + *d = (uint64_t)s->val.u32; + break; + case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break; + case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break; + case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break; + default: + // all the others are plain pointer types + *d = (uint64_t)s->val.p; + break; + } + } +} + +/* + * EXPORT_XPCOM_API(nsresult) + * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ +__asm__( + "#### NS_InvokeByIndex ####\n" +".text\n\t" + ".align 5\n\t" + ".globl NS_InvokeByIndex\n\t" + ".ent NS_InvokeByIndex\n" +"NS_InvokeByIndex:\n\t" + ".frame $15,32,$26,0\n\t" + ".mask 0x4008000,-32\n\t" + "ldgp $29,0($27)\n" +"$NS_InvokeByIndex..ng:\n\t" + "subq $30,32,$30\n\t" + "stq $26,0($30)\n\t" + "stq $15,8($30)\n\t" + "bis $30,$30,$15\n\t" + ".prologue 1\n\t" + + /* + * Allocate enough stack space to hold the greater of 6 or "paramCount"+1 + * parameters. (+1 for "this" pointer) Room for at least 6 parameters + * is required for storage of those passed via registers. + */ + + "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */ + "cmplt $2,$18,$1\n\t" + "cmovne $1,$18,$2\n\t" + "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */ + "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */ + "subq $30,$1,$30\n\t" + + "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */ + "stq $17,16($15)\n\t" /* save "methodIndex" */ + + "addq $30,8,$16\n\t" /* pass stack pointer */ + "bis $18,$18,$17\n\t" /* pass "paramCount" */ + "bis $19,$19,$18\n\t" /* pass "params" */ + "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */ + + /* + * Copy the first 6 parameters to registers and remove from stack frame. + * Both the integer and floating point registers are set for each parameter + * except the first which is the "this" pointer. (integer only) + * The floating point registers are all set as doubles since the + * invoke_copy_to_stack function should have converted the floats. + */ + "ldq $16,0($30)\n\t" /* integer registers */ + "ldq $17,8($30)\n\t" + "ldq $18,16($30)\n\t" + "ldq $19,24($30)\n\t" + "ldq $20,32($30)\n\t" + "ldq $21,40($30)\n\t" + "ldt $f17,8($30)\n\t" /* floating point registers */ + "ldt $f18,16($30)\n\t" + "ldt $f19,24($30)\n\t" + "ldt $f20,32($30)\n\t" + "ldt $f21,40($30)\n\t" + + "addq $30,48,$30\n\t" /* remove params from stack */ + + /* + * Call the virtual function with the constructed stack frame. + */ + "bis $16,$16,$1\n\t" /* load "this" */ + "ldq $2,16($15)\n\t" /* load "methodIndex" */ + "ldq $1,0($1)\n\t" /* load vtable */ + "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */ + "addq $1,$2,$1\n\t" + "ldq $27,0($1)\n\t" /* load address of function */ + "jsr $26,($27),0\n\t" /* call virtual function */ + "ldgp $29,0($26)\n\t" + + "bis $15,$15,$30\n\t" + "ldq $26,0($30)\n\t" + "ldq $15,8($30)\n\t" + "addq $30,32,$30\n\t" + "ret $31,($26),1\n\t" + ".end NS_InvokeByIndex" + ); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp new file mode 100644 index 000000000..6f2934cbc --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp @@ -0,0 +1,130 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +// Remember that these 'words' are 32bit DWORDS + +extern "C" { + static uint32_t + invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) + { + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; + } + + void + invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) + { + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + // 8 and 16 bit types should be promoted to 32 bits when copying + // onto the stack. + case nsXPTType::T_I8 : *((uint32_t*)d) = s->val.i8; break; + case nsXPTType::T_I16 : *((uint32_t*)d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((uint32_t*)d) = s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*)d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } + } +} + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + uint32_t result, n; + + n = invoke_count_words(paramCount, params) * 4; + + __asm__ __volatile__( + "subl %5, %%sp\n\t" /* make room for params */ + "movel %4, %%sp@-\n\t" + "movel %3, %%sp@-\n\t" + "pea %%sp@(8)\n\t" + "jbsr invoke_copy_to_stack\n\t" /* copy params */ + "addw #12, %%sp\n\t" + "movel %1, %%sp@-\n\t" + "movel %1@, %%a0\n\t" + "movel %%a0@(%2:l:4), %%a0\n\t" + "jbsr %%a0@\n\t" /* safe to not cleanup sp */ + "lea %%sp@(4,%5:l), %%sp\n\t" + "movel %%d0, %0" + : "=d" (result) /* %0 */ + : "a" (that), /* %1 */ + "d" (methodIndex), /* %2 */ + "g" (paramCount), /* %3 */ + "g" (params), /* %4 */ + "d" (n) /* %5 */ + : "a0", "a1", "d0", "d1", "memory" + ); + + return result; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp new file mode 100644 index 000000000..573dfb00c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp @@ -0,0 +1,195 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + if (gpr < 5) gpr++; else overflow++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_I64 : + if (gpr < 4) gpr+=2; else gpr=5, overflow+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_U64 : + if (gpr < 4) gpr+=2; else gpr=5, overflow+=2; + break; + case nsXPTType::T_FLOAT : + if (fpr < 2) fpr++; else overflow++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 2) fpr++; else overflow+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + if (gpr < 5) gpr++; else overflow++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) gpr++; else overflow++; + break; + } + } + /* Round up number of overflow words to ensure stack + stays aligned to 8 bytes. */ + return (overflow + 1) & ~1; +} + +static void +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d_ov, uint32_t overflow) +{ + uint32_t *d_gpr = d_ov + overflow; + uint64_t *d_fpr = (uint64_t *)(d_gpr + 4); + uint32_t gpr = 1 /*this*/, fpr = 0; + + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + if (gpr < 5) + *((void**)d_gpr) = s->ptr, d_gpr++, gpr++; + else + *((void**)d_ov ) = s->ptr, d_ov++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + *((int32_t*) d_gpr) = s->val.i8, d_gpr++, gpr++; + else + *((int32_t*) d_ov ) = s->val.i8, d_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + *((int32_t*) d_gpr) = s->val.i16, d_gpr++, gpr++; + else + *((int32_t*) d_ov ) = s->val.i16, d_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + *((int32_t*) d_gpr) = s->val.i32, d_gpr++, gpr++; + else + *((int32_t*) d_ov ) = s->val.i32, d_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 4) + *((int64_t*) d_gpr) = s->val.i64, d_gpr+=2, gpr+=2; + else + *((int64_t*) d_ov ) = s->val.i64, d_ov+=2, gpr=5; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + *((uint32_t*) d_gpr) = s->val.u8, d_gpr++, gpr++; + else + *((uint32_t*) d_ov ) = s->val.u8, d_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.u16, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.u16, d_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.u32, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.u32, d_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 4) + *((uint64_t*)d_gpr) = s->val.u64, d_gpr+=2, gpr+=2; + else + *((uint64_t*)d_ov ) = s->val.u64, d_ov+=2, gpr=5; + break; + case nsXPTType::T_FLOAT : + if (fpr < 2) + *((float*) d_fpr) = s->val.f, d_fpr++, fpr++; + else + *((float*) d_ov ) = s->val.f, d_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 2) + *((double*) d_fpr) = s->val.d, d_fpr++, fpr++; + else + *((double*) d_ov ) = s->val.d, d_ov+=2; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.b, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.b, d_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.c, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.c, d_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.wc, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.wc, d_ov++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) + *((void**) d_gpr) = s->val.p, d_gpr++, gpr++; + else + *((void**) d_ov ) = s->val.p, d_ov++; + break; + } + } +} + +typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t, uint32_t, double, double); + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); + vtable_func method = vtable[methodIndex]; + uint32_t overflow = invoke_count_words (paramCount, params); + uint32_t *stack_space = reinterpret_cast<uint32_t *>(__builtin_alloca((overflow + 8 /* 4 32-bits gpr + 2 64-bits fpr */) * 4)); + + invoke_copy_to_stack(paramCount, params, stack_space, overflow); + + uint32_t *d_gpr = stack_space + overflow; + double *d_fpr = reinterpret_cast<double *>(d_gpr + 4); + + return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1]); +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp new file mode 100644 index 000000000..86478a850 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp @@ -0,0 +1,190 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + if (gpr < 5) gpr++; else overflow++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + case nsXPTType::T_I64 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + case nsXPTType::T_U64 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_FLOAT : + case nsXPTType::T_DOUBLE : + if (fpr < 4) fpr++; else overflow++; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + if (gpr < 5) gpr++; else overflow++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) gpr++; else overflow++; + break; + } + } + /* Round up number of overflow words to ensure stack + stays aligned to 8 bytes. */ + return (overflow + 1) & ~1; +} + +static void +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint64_t* d_ov, uint32_t overflow) +{ + uint64_t *d_gpr = d_ov + overflow; + uint64_t *d_fpr = (uint64_t *)(d_gpr + 4); + uint32_t gpr = 1 /*this*/, fpr = 0; + + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + if (gpr < 5) + *((void**)d_gpr) = s->ptr, d_gpr++, gpr++; + else + *((void**)d_ov ) = s->ptr, d_ov++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i8, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i8, d_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i16, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i16, d_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i32, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i32, d_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i64, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i64, d_ov++; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + *((uint64_t*) d_gpr) = s->val.u8, d_gpr++, gpr++; + else + *((uint64_t*) d_ov ) = s->val.u8, d_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.u16, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.u16, d_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.u32, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.u32, d_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.u64, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.u64, d_ov++; + break; + case nsXPTType::T_FLOAT : + if (fpr < 4) + *((float*) d_fpr) = s->val.f, d_fpr++, fpr++; + else + *(((float*) d_ov )+1) = s->val.f, d_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 4) + *((double*) d_fpr) = s->val.d, d_fpr++, fpr++; + else + *((double*) d_ov ) = s->val.d, d_ov++; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.b, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.b, d_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.c, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.c, d_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.wc, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.wc, d_ov++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) + *((void**) d_gpr) = s->val.p, d_gpr++, gpr++; + else + *((void**) d_ov ) = s->val.p, d_ov++; + break; + } + } +} + +typedef nsresult (*vtable_func)(nsISupports *, uint64_t, uint64_t, uint64_t, uint64_t, double, double, double, double); + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); + vtable_func method = vtable[methodIndex]; + uint64_t overflow = invoke_count_words (paramCount, params); + uint64_t *stack_space = reinterpret_cast<uint64_t *>(__builtin_alloca((overflow + 8 /* 4 64-bits gpr + 4 64-bits fpr */) * 8)); + uint64_t result; + + invoke_copy_to_stack(paramCount, params, stack_space, overflow); + + uint64_t *d_gpr = stack_space + overflow; + double *d_fpr = reinterpret_cast<double *>(d_gpr + 4); + + return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1], d_fpr[2], d_fpr[3]); +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp new file mode 100644 index 000000000..f6585e7f0 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#include <stdint.h> + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + // Count a word for a0 even though it's never stored or loaded + // We do this only for alignment of register pairs. + uint32_t result = 1; + for (uint32_t i = 0; i < paramCount; i++, result++, s++) + { + if (s->IsPtrData()) + continue; + + switch(s->type) + { + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : + if (result & 1) + result++; + result++; + break; + + default: + break; + } + } + return (result + 1) & ~(uint32_t)1; +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + nsXPTCVariant* s) +{ + // Skip the unused a0 slot, which we keep only for register pair alignment. + d++; + + for (uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if (s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + + switch(s->type) + { + case nsXPTType::T_I8 : *d = (uint32_t) s->val.i8; break; + case nsXPTType::T_I16 : *d = (uint32_t) s->val.i16; break; + case nsXPTType::T_I32 : *d = (uint32_t) s->val.i32; break; + case nsXPTType::T_I64 : + if ((intptr_t)d & 4) d++; + *((int64_t*) d) = s->val.i64; d++; + break; + case nsXPTType::T_U8 : *d = (uint32_t) s->val.u8; break; + case nsXPTType::T_U16 : *d = (uint32_t) s->val.u16; break; + case nsXPTType::T_U32 : *d = (uint32_t) s->val.u32; break; + case nsXPTType::T_U64 : + if ((intptr_t)d & 4) d++; + *((uint64_t*) d) = s->val.u64; d++; + break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : + if ((intptr_t)d & 4) d++; + *((double*) d) = s->val.d; d++; + break; + case nsXPTType::T_BOOL : *d = (bool) s->val.b; break; + case nsXPTType::T_CHAR : *d = (char) s->val.c; break; + case nsXPTType::T_WCHAR : *d = (wchar_t) s->val.wc; break; + default: + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp new file mode 100644 index 000000000..1dd54f96f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp @@ -0,0 +1,142 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64) +#error "This code is for MIPS n32/n64 only" +#endif + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return paramCount; +} + +extern "C" void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, + nsXPTCVariant* s, uint64_t *regs) +{ +#define N_ARG_REGS 7 /* 8 regs minus 1 for "this" ptr */ + + for (uint32_t i = 0; i < paramCount; i++, s++) + { + if (s->IsPtrData()) { + if (i < N_ARG_REGS) + regs[i] = (uint64_t)s->ptr; + else + *d++ = (uint64_t)s->ptr; + continue; + } + switch (s->type) { + // + // signed types first + // + case nsXPTType::T_I8: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i8; + else + *d++ = s->val.i8; + break; + case nsXPTType::T_I16: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i16; + else + *d++ = s->val.i16; + break; + case nsXPTType::T_I32: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i32; + else + *d++ = s->val.i32; + break; + case nsXPTType::T_I64: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i64; + else + *d++ = s->val.i64; + break; + // + // unsigned types next + // + case nsXPTType::T_U8: + if (i < N_ARG_REGS) + regs[i] = s->val.u8; + else + *d++ = s->val.u8; + break; + case nsXPTType::T_U16: + if (i < N_ARG_REGS) + regs[i] = s->val.u16; + else + *d++ = s->val.u16; + break; + case nsXPTType::T_U32: + if (i < N_ARG_REGS) + // 32-bit values need to be sign-extended + // in register, so use the signed value. + regs[i] = s->val.i32; + else + *d++ = s->val.u32; + break; + case nsXPTType::T_U64: + if (i < N_ARG_REGS) + regs[i] = s->val.u64; + else + *d++ = s->val.u64; + break; + case nsXPTType::T_FLOAT: + if (i < N_ARG_REGS) + *(float*)®s[i] = s->val.f; + else + *(float*)d++ = s->val.f; + break; + case nsXPTType::T_DOUBLE: + if (i < N_ARG_REGS) + *(double*)®s[i] = s->val.d; + else + *(double*)d++ = s->val.d; + break; + case nsXPTType::T_BOOL: + if (i < N_ARG_REGS) + regs[i] = s->val.b; + else + *d++ = s->val.b; + break; + case nsXPTType::T_CHAR: + if (i < N_ARG_REGS) + regs[i] = s->val.c; + else + *d++ = s->val.c; + break; + case nsXPTType::T_WCHAR: + if (i < N_ARG_REGS) + regs[i] = s->val.wc; + else + *d++ = s->val.wc; + break; + default: + // all the others are plain pointer types + if (i < N_ARG_REGS) + regs[i] = (uint64_t)s->val.p; + else + *d++ = (uint64_t)s->val.p; + break; + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp new file mode 100644 index 000000000..47e0e7666 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp @@ -0,0 +1,143 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +// Remember that these 'words' are 32bit DWORDS + +#if !defined(__NetBSD__) || !defined(__m68k__) +#error This code is for NetBSD/m68k only +#endif + +extern "C" { + static uint32_t + invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) + { + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; + } + + static void + invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) + { + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + // 8 and 16 bit types should be promoted to 32 bits when copying + // onto the stack. + case nsXPTType::T_I8 : *((uint32_t*)d) = s->val.i8; break; + case nsXPTType::T_I16 : *((uint32_t*)d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((uint32_t*)d) = s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*)d) = s->val.c; break; + // wchar_t is an int (32 bits) on NetBSD + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } + } +} + +XPTC_PUBLIC_API(nsresult) +XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + uint32_t result; + + __asm__ __volatile__( + "movl %4, sp@-\n\t" + "movl %3, sp@-\n\t" + "jbsr _invoke_count_words\n\t" /* count words */ + "addql #8, sp\n\t" + "lsll #2, d0\n\t" /* *= 4 */ + "movl sp, a2\n\t" /* save original sp */ + "subl d0, sp\n\t" /* make room for params */ + "movl sp, a0\n\t" + "movl %4, sp@-\n\t" + "movl %3, sp@-\n\t" + "movl a0, sp@-\n\t" + "jbsr _invoke_copy_to_stack\n\t" /* copy params */ + "addl #12, sp\n\t" + "movl %1, a0\n\t" + "movl a0@, a1\n\t" + "movl %2, d0\n\t" /* function index */ + "movl a0, d1\n\t" + "movw a1@(8,d0:l:8), a0\n\t" + "addl a0, d1\n\t" + "movl a1@(12,d0:l:8), a1\n\t" + "movl d1, sp@-\n\t" + "jbsr a1@\n\t" + "movl a2, sp\n\t" /* restore original sp */ + "movl d0, %0\n\t" + : "=g" (result) /* %0 */ + : "g" (that), /* %1 */ + "g" (methodIndex), /* %2 */ + "g" (paramCount), /* %3 */ + "g" (params) /* %4 */ + : "a0", "a1", "a2", "d0", "d1", "memory" + ); + + return result; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp new file mode 100644 index 000000000..0e6d28fbd --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp @@ -0,0 +1,149 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#if _HPUX +#error "This code is for HP-PA RISC 32 bit mode only" +#endif + +#include <alloca.h> + +typedef unsigned nsXPCVariant; + +extern "C" int32_t +invoke_count_bytes(nsISupports* that, const uint32_t methodIndex, + const uint32_t paramCount, const nsXPTCVariant* s) +{ + int32_t result = 4; /* variant records do not include self pointer */ + + /* counts the number of bytes required by the argument stack, + 64 bit integer, and double requires 8 bytes. All else requires + 4 bytes. + */ + + { + uint32_t indx; + for (indx = paramCount; indx > 0; --indx, ++s) + { + if (! s->IsPtrData()) + { + if (s->type == nsXPTType::T_I64 || s->type == nsXPTType::T_U64 || + s->type == nsXPTType::T_DOUBLE) + { + /* 64 bit integer and double aligned on 8 byte boundaries */ + result += (result & 4) + 8; + continue; + } + } + result += 4; /* all other cases use 4 bytes */ + } + } + result -= 72; /* existing stack buffer is 72 bytes */ + if (result < 0) + return 0; + { + /* round up to 64 bytes boundary */ + int32_t remainder = result & 63; + return (remainder == 0) ? result : (result + 64 - remainder); + } +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, + const uint32_t paramCount, nsXPTCVariant* s) +{ + + typedef struct + { + uint32_t hi; + uint32_t lo; + } DU; + + uint32_t* dest = d; + nsXPTCVariant* source = s; + /* we clobber param vars by copying stuff on stack, have to use local var */ + + uint32_t floatflags = 0; + /* flag indicating which floating point registers to load */ + + uint32_t regwords = 1; /* register 26 is reserved for ptr to 'that' */ + uint32_t indx; + + for (indx = paramCount; indx > 0; --indx, --dest, ++source) + { + if (source->IsPtrData()) + { + *((void**) dest) = source->ptr; + ++regwords; + continue; + } + switch (source->type) + { + case nsXPTType::T_I8 : *((int32_t*) dest) = source->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) dest) = source->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) dest) = source->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + if (regwords & 1) + { + /* align on double word boundary */ + --dest; + ++regwords; + } + *((uint32_t*) dest) = ((DU *) source)->lo; + *((uint32_t*) --dest) = ((DU *) source)->hi; + /* big endian - hi word in low addr */ + regwords += 2; + continue; + case nsXPTType::T_DOUBLE : + if (regwords & 1) + { + /* align on double word boundary */ + --dest; + ++regwords; + } + switch (regwords) /* load double precision float register */ + { + case 2: + floatflags |= 1; + } + *((uint32_t*) dest) = ((DU *) source)->lo; + *((uint32_t*) --dest) = ((DU *) source)->hi; + /* big endian - hi word in low addr */ + regwords += 2; + continue; + case nsXPTType::T_FLOAT : + switch (regwords) /* load single precision float register */ + { + case 1: + floatflags |= 2; + break; + case 2: + floatflags |= 4; + break; + case 3: + floatflags |= 8; + } + *((float*) dest) = source->val.f; + break; + case nsXPTType::T_U8 : *((uint32_t*) (dest)) = source->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) (dest)) = source->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) (dest)) = source->val.u32; break; + case nsXPTType::T_BOOL : *((uint32_t*) (dest)) = source->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) (dest)) = source->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) (dest)) = source->val.wc; break; + + default: + // all the others are plain pointer types + *((void**) dest) = source->val.p; + } + ++regwords; + } + return floatflags; +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp new file mode 100644 index 000000000..c93dc4621 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp @@ -0,0 +1,97 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +// The purpose of NS_InvokeByIndex() is to map a platform +// independent call to the platform ABI. To do that, +// NS_InvokeByIndex() has to determine the method to call via vtable +// access. The parameters for the method are read from the +// nsXPTCVariant* and prepared for the native ABI. + +// The PowerPC64 platform ABI can be found here: +// http://www.freestandards.org/spec/ELF/ppc64/ +// and in particular: +// http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL + +#include <stdio.h> +#include "xptcprivate.h" + +// 8 integral parameters are passed in registers, not including 'that' +#define GPR_COUNT 7 + +// 8 floating point parameters are passed in registers, floats are +// promoted to doubles when passed in registers +#define FPR_COUNT 13 + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return uint32_t(((paramCount * 2) + 3) & ~3); +} + +extern "C" void +invoke_copy_to_stack(uint64_t* gpregs, + double* fpregs, + uint32_t paramCount, + nsXPTCVariant* s, + uint64_t* d) +{ + uint64_t tempu64; + + for(uint32_t i = 0; i < paramCount; i++, s++) { + if(s->IsPtrData()) + tempu64 = (uint64_t) s->ptr; + else { + switch(s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: tempu64 = s->val.i8; break; + case nsXPTType::T_I16: tempu64 = s->val.i16; break; + case nsXPTType::T_I32: tempu64 = s->val.i32; break; + case nsXPTType::T_I64: tempu64 = s->val.i64; break; + case nsXPTType::T_U8: tempu64 = s->val.u8; break; + case nsXPTType::T_U16: tempu64 = s->val.u16; break; + case nsXPTType::T_U32: tempu64 = s->val.u32; break; + case nsXPTType::T_U64: tempu64 = s->val.u64; break; + case nsXPTType::T_BOOL: tempu64 = s->val.b; break; + case nsXPTType::T_CHAR: tempu64 = s->val.c; break; + case nsXPTType::T_WCHAR: tempu64 = s->val.wc; break; + default: tempu64 = (uint64_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { + if (i < FPR_COUNT) + fpregs[i] = s->val.d; + else + *(double *)d = s->val.d; + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { + if (i < FPR_COUNT) { + fpregs[i] = s->val.f; // if passed in registers, floats are promoted to doubles + } else { + float *p = (float *)d; +#ifndef __LITTLE_ENDIAN__ + p++; +#endif + *p = s->val.f; + } + } + else { + if (i < GPR_COUNT) + gpregs[i] = tempu64; + else + *d = tempu64; + } + if (i >= 7) + d++; + } +} + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp new file mode 100644 index 000000000..ba2a5dab0 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#ifndef AIX +#error "This code is for PowerPC only" +#endif + +extern "C" void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount, fpCount = 0; + double *l_fprData = fprData; + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if(l_s->IsPtrData()) + { + *((void**)l_d) = l_s->ptr; + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_DOUBLE : + *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.d; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : + *((float*) l_d) = l_s->val.f; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.f; + break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp new file mode 100644 index 000000000..616c2f687 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#ifdef _AIX + +extern "C" void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint64_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount, fpCount = 0; + double *l_fprData = fprData; + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if(l_s->IsPtrData()) + { + *l_d = (uint64_t)l_s->ptr; + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8: *l_d = (uint64_t)l_s->val.i8; break; + case nsXPTType::T_I16: *l_d = (uint64_t)l_s->val.i16; break; + case nsXPTType::T_I32: *l_d = (uint64_t)l_s->val.i32; break; + case nsXPTType::T_I64: *l_d = (uint64_t)l_s->val.i64; break; + case nsXPTType::T_U8: *l_d = (uint64_t)l_s->val.u8; break; + case nsXPTType::T_U16: *l_d = (uint64_t)l_s->val.u16; break; + case nsXPTType::T_U32: *l_d = (uint64_t)l_s->val.u32; break; + case nsXPTType::T_U64: *l_d = (uint64_t)l_s->val.u64; break; + case nsXPTType::T_BOOL: *l_d = (uint64_t)l_s->val.b; break; + case nsXPTType::T_CHAR: *l_d = (uint64_t)l_s->val.c; break; + case nsXPTType::T_WCHAR: *l_d = (uint64_t)l_s->val.wc; break; + + case nsXPTType::T_DOUBLE: + *((double*)l_d) = l_s->val.d; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.d; + break; + case nsXPTType::T_FLOAT: + *((float*)l_d) = l_s->val.f; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.f; + break; + default: + // all the others are plain pointer types + *l_d = (uint64_t)l_s->val.p; + break; + } + } +} +#endif + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp new file mode 100644 index 000000000..deb72db8f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp @@ -0,0 +1,128 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +// The purpose of NS_InvokeByIndex() is to map a platform +// indepenpent call to the platform ABI. To do that, +// NS_InvokeByIndex() has to determine the method to call via vtable +// access. The parameters for the method are read from the +// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC +// ABI this means that the first 8 integral and floating point +// parameters are passed in registers. + +#include "xptcprivate.h" + +// 8 integral parameters are passed in registers +#define GPR_COUNT 8 + +// With hardfloat support 8 floating point parameters are passed in registers, +// floats are promoted to doubles when passed in registers +// In Softfloat mode, everything is handled via gprs +#ifndef __NO_FPRS__ +#define FPR_COUNT 8 +#endif +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return uint32_t(((paramCount * 2) + 3) & ~3); +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, + uint32_t paramCount, + nsXPTCVariant* s, + uint32_t* gpregs, + double* fpregs) +{ + uint32_t gpr = 1; // skip one GP reg for 'that' +#ifndef __NO_FPRS__ + uint32_t fpr = 0; +#endif + uint32_t tempu32; + uint64_t tempu64; + + for(uint32_t i = 0; i < paramCount; i++, s++) { + if(s->IsPtrData()) { + if(s->type == nsXPTType::T_JSVAL) + tempu32 = (uint32_t) &s->ptr; + else + tempu32 = (uint32_t) s->ptr; + } + else { + switch(s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: tempu32 = s->val.i8; break; + case nsXPTType::T_I16: tempu32 = s->val.i16; break; + case nsXPTType::T_I32: tempu32 = s->val.i32; break; + case nsXPTType::T_I64: tempu64 = s->val.i64; break; + case nsXPTType::T_U8: tempu32 = s->val.u8; break; + case nsXPTType::T_U16: tempu32 = s->val.u16; break; + case nsXPTType::T_U32: tempu32 = s->val.u32; break; + case nsXPTType::T_U64: tempu64 = s->val.u64; break; + case nsXPTType::T_BOOL: tempu32 = s->val.b; break; + case nsXPTType::T_CHAR: tempu32 = s->val.c; break; + case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; + default: tempu32 = (uint32_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.d; +#else + if (gpr & 1) + gpr++; + if ((gpr + 1) < GPR_COUNT) { + *((double*) &gpregs[gpr]) = s->val.d; + gpr += 2; + } +#endif + else { + if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack + *((double*) d) = s->val.d; + d += 2; + } + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles +#else + if (gpr < GPR_COUNT) + *((float*) &gpregs[gpr++]) = s->val.f; +#endif + else + *((float*) d++) = s->val.f; + } + else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 + || s->type == nsXPTType::T_U64)) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + if ((gpr + 1) < GPR_COUNT) { + *((uint64_t*) &gpregs[gpr]) = tempu64; + gpr += 2; + } + else { + if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack + *((uint64_t*) d) = tempu64; + d += 2; + } + } + else { + if (gpr < GPR_COUNT) + gpregs[gpr++] = tempu32; + else + *d++ = tempu32; + } + + } +} + +extern "C" +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp new file mode 100644 index 000000000..515e8c50b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp @@ -0,0 +1,115 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +// The purpose of XPTC_InvokeByIndex() is to map a platform +// indepenpent call to the platform ABI. To do that, +// XPTC_InvokeByIndex() has to determine the method to call via vtable +// access. The parameters for the method are read from the +// nsXPTCVariant* and prepared for the native ABI. For the Linux/PPC +// ABI this means that the first 8 integral and floating point +// parameters are passed in registers. + +#include "xptcprivate.h" + +// 8 integral parameters are passed in registers +#define GPR_COUNT 8 + +// 8 floating point parameters are passed in registers, floats are +// promoted to doubles when passed in registers +#define FPR_COUNT 8 + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return uint32_t(((paramCount * 2) + 3) & ~3); +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, + uint32_t paramCount, + nsXPTCVariant* s, + uint32_t* gpregs, + double* fpregs) +{ + uint32_t gpr = 1; // skip one GP reg for 'that' + uint32_t fpr = 0; + uint32_t tempu32; + uint64_t tempu64; + + for(uint32_t i = 0; i < paramCount; i++, s++) { + if(s->IsPtrData()) { + if(s->type == nsXPTType::T_JSVAL) + tempu32 = (uint32_t) &(s->ptr); + else + tempu32 = (uint32_t) s->ptr; + } else { + switch(s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: tempu32 = s->val.i8; break; + case nsXPTType::T_I16: tempu32 = s->val.i16; break; + case nsXPTType::T_I32: tempu32 = s->val.i32; break; + case nsXPTType::T_I64: tempu64 = s->val.i64; break; + case nsXPTType::T_U8: tempu32 = s->val.u8; break; + case nsXPTType::T_U16: tempu32 = s->val.u16; break; + case nsXPTType::T_U32: tempu32 = s->val.u32; break; + case nsXPTType::T_U64: tempu64 = s->val.u64; break; + case nsXPTType::T_BOOL: tempu32 = s->val.b; break; + case nsXPTType::T_CHAR: tempu32 = s->val.c; break; + case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; + default: tempu32 = (uint32_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.d; + else { + if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack + *((double*) d) = s->val.d; + d += 2; + if (gpr < GPR_COUNT) + gpr += 2; + } + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles + else { + *((float*) d) = s->val.f; + d += 1; + if (gpr < GPR_COUNT) + gpr += 1; + } + } + else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 + || s->type == nsXPTType::T_U64)) { + if ((gpr + 1) < GPR_COUNT) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + *((uint64_t*) &gpregs[gpr]) = tempu64; + gpr += 2; + } + else { + if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack + *((uint64_t*) d) = tempu64; + d += 2; + } + } + else { + if (gpr < GPR_COUNT) + gpregs[gpr++] = tempu32; + else + *d++ = tempu32; + } + + } +} + +extern "C" +XPTC_PUBLIC_API(nsresult) +XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp new file mode 100644 index 000000000..5353220fe --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp @@ -0,0 +1,109 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +// The purpose of NS_InvokeByIndex() is to map a platform +// indepenpent call to the platform ABI. To do that, +// NS_InvokeByIndex() has to determine the method to call via vtable +// access. The parameters for the method are read from the +// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC +// ABI this means that the first 8 integral and floating point +// parameters are passed in registers. + +#include "xptcprivate.h" + +// 8 integral parameters are passed in registers +#define GPR_COUNT 8 + +// 8 floating point parameters are passed in registers, floats are +// promoted to doubles when passed in registers +#define FPR_COUNT 8 + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return uint32_t(((paramCount * 2) + 3) & ~3); +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, + uint32_t paramCount, + nsXPTCVariant* s, + uint32_t* gpregs, + double* fpregs) +{ + uint32_t gpr = 1; // skip one GP reg for 'that' + uint32_t fpr = 0; + uint32_t tempu32; + uint64_t tempu64; + + for(uint32_t i = 0; i < paramCount; i++, s++) { + if(s->IsPtrData()) { + if(s->type == nsXPTType::T_JSVAL) + tempu32 = (uint32_t) &(s->ptr); + else + tempu32 = (uint32_t) s->ptr; + } else { + switch(s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: tempu32 = s->val.i8; break; + case nsXPTType::T_I16: tempu32 = s->val.i16; break; + case nsXPTType::T_I32: tempu32 = s->val.i32; break; + case nsXPTType::T_I64: tempu64 = s->val.i64; break; + case nsXPTType::T_U8: tempu32 = s->val.u8; break; + case nsXPTType::T_U16: tempu32 = s->val.u16; break; + case nsXPTType::T_U32: tempu32 = s->val.u32; break; + case nsXPTType::T_U64: tempu64 = s->val.u64; break; + case nsXPTType::T_BOOL: tempu32 = s->val.b; break; + case nsXPTType::T_CHAR: tempu32 = s->val.c; break; + case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; + default: tempu32 = (uint32_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.d; + else { + if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack + *((double*) d) = s->val.d; + d += 2; + } + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles + else + *((float*) d++) = s->val.f; + } + else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 + || s->type == nsXPTType::T_U64)) { + if ((gpr + 1) < GPR_COUNT) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + *((uint64_t*) &gpregs[gpr]) = tempu64; + gpr += 2; + } + else { + if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack + *((uint64_t*) d) = tempu64; + d += 2; + } + } + else { + if (gpr < GPR_COUNT) + gpregs[gpr++] = tempu32; + else + *d++ = tempu32; + } + + } +} + +extern "C" +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp new file mode 100644 index 000000000..1a40cfeea --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp @@ -0,0 +1,113 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + /* fprintf(stderr,"invoke_count_words(%d,%p)\n",paramCount, s);*/ + + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData) +{ + uint32_t fpCount = 0; + + /* fprintf(stderr,"invoke_copy_to_stack(%p, %d, %p, %p)\n", d, paramCount, s, fprData);*/ + + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint32_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; + if (fpCount < 13) + fprData[fpCount++] = s->val.f; + break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; + if (fpCount < 13) + fprData[fpCount++] = s->val.d; + break; + case nsXPTType::T_BOOL : *((uint32_t*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((uint32_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp new file mode 100644 index 000000000..050f9414d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(__sparc) && !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +extern "C" uint64_t +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + /* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. + */ + uint64_t *l_d = d; + nsXPTCVariant *l_s = s; + uint64_t l_paramCount = paramCount; + uint64_t regCount = 0; // return the number of registers to load from the stack + + for(uint64_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + + if (l_s->IsPtrData()) + { + *l_d = (uint64_t)l_s->ptr; + continue; + } + switch (l_s->type) + { + case nsXPTType::T_I8 : *((int64_t*)l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int64_t*)l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int64_t*)l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*)l_d) = l_s->val.i64; break; + + case nsXPTType::T_U8 : *((uint64_t*)l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint64_t*)l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint64_t*)l_d) = l_s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)l_d) = l_s->val.u64; break; + + /* in the case of floats, we want to put the bits in to the + 64bit space right justified... floats in the parameter array on + sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip + the space that would be occupied by %f0, %f2, etc. + */ + case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break; + case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break; + case nsXPTType::T_BOOL : *((int64_t*)l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint64_t*)l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int64_t*)l_d) = l_s->val.wc; break; + + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + + return regCount; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp new file mode 100644 index 000000000..126ef1dad --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp @@ -0,0 +1,131 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* solaris defines __sparc for workshop compilers and + linux defines __sparc__ */ + +#if !defined(__sparc) && !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +typedef unsigned nsXPCVariant; + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + // nuts, I know there's a cooler way of doing this, but it's late + // now and it'll probably come to me in the morning. + if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment + return result; +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount; + uint32_t regCount = 0; // return the number of registers to load from the stack + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + if(l_s->IsPtrData()) + { + if(l_s->type == nsXPTType::T_JSVAL) + { + // On SPARC, we need to pass a pointer to HandleValue + *((void**)l_d) = &l_s->ptr; + } else + { + *((void**)l_d) = l_s->ptr; + } + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + if (regCount < 5) regCount++; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + return regCount; +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp new file mode 100644 index 000000000..9b2e4f858 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp @@ -0,0 +1,128 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +typedef unsigned nsXPCVariant; + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + // nuts, I know there's a cooler way of doing this, but it's late + // now and it'll probably come to me in the morning. + if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment + return result; +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount; + uint32_t regCount = 0; // return the number of registers to load from the stack + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + if(l_s->IsPtrData()) + { + if(l_s->type == nsXPTType::T_JSVAL) + { + // On SPARC, we need to pass a pointer to HandleValue + *((void**)l_d) = &l_s->ptr; + } else + { + *((void**)l_d) = l_s->ptr; + } + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + if (regCount < 5) regCount++; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + return regCount; +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp new file mode 100644 index 000000000..126ef1dad --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp @@ -0,0 +1,131 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* solaris defines __sparc for workshop compilers and + linux defines __sparc__ */ + +#if !defined(__sparc) && !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +typedef unsigned nsXPCVariant; + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + // nuts, I know there's a cooler way of doing this, but it's late + // now and it'll probably come to me in the morning. + if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment + return result; +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount; + uint32_t regCount = 0; // return the number of registers to load from the stack + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + if(l_s->IsPtrData()) + { + if(l_s->type == nsXPTType::T_JSVAL) + { + // On SPARC, we need to pass a pointer to HandleValue + *((void**)l_d) = &l_s->ptr; + } else + { + *((void**)l_d) = l_s->ptr; + } + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + if (regCount < 5) regCount++; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + return regCount; +} + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp new file mode 100644 index 000000000..0d2d6b0a8 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(__sparc) && !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +/* Prototype specifies unmangled function name */ +extern "C" uint64_t +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s); + +extern "C" uint64_t +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + /* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. + */ + uint64_t *l_d = d; + nsXPTCVariant *l_s = s; + uint64_t l_paramCount = paramCount; + uint64_t regCount = 0; // return the number of registers to load from the stack + + for(uint64_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + + if (l_s->IsPtrData()) + { + *l_d = (uint64_t)l_s->ptr; + continue; + } + switch (l_s->type) + { + case nsXPTType::T_I8 : *((int64_t*)l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int64_t*)l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int64_t*)l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*)l_d) = l_s->val.i64; break; + + case nsXPTType::T_U8 : *((uint64_t*)l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint64_t*)l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint64_t*)l_d) = l_s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)l_d) = l_s->val.u64; break; + + /* in the case of floats, we want to put the bits in to the + 64bit space right justified... floats in the parameter array on + sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip + the space that would be occupied by %f0, %f2, etc. + */ + case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break; + case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break; + case nsXPTType::T_BOOL : *((uint64_t*)l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint64_t*)l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int64_t*)l_d) = l_s->val.wc; break; + + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + + return regCount; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp new file mode 100644 index 000000000..0d3424366 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp @@ -0,0 +1,149 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +#include "xptcprivate.h" +#include "alloca.h" + +// 6 integral parameters are passed in registers +const uint32_t GPR_COUNT = 6; + +// 8 floating point parameters are passed in SSE registers +const uint32_t FPR_COUNT = 8; + +// Remember that these 'words' are 64-bit long +static inline void +invoke_count_words(uint32_t paramCount, nsXPTCVariant * s, + uint32_t & nr_gpr, uint32_t & nr_fpr, uint32_t & nr_stack) +{ + nr_gpr = 1; // skip one GP register for 'that' + nr_fpr = 0; + nr_stack = 0; + + /* Compute number of eightbytes of class MEMORY. */ + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (!s->IsPtrData() + && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) { + if (nr_fpr < FPR_COUNT) + nr_fpr++; + else + nr_stack++; + } + else { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + nr_stack++; + } + } +} + +static void +invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s, + uint64_t * gpregs, double * fpregs) +{ + uint32_t nr_gpr = 1; // skip one GP register for 'that' + uint32_t nr_fpr = 0; + uint64_t value; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsPtrData()) + value = (uint64_t) s->ptr; + else { + switch (s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: value = s->val.i8; break; + case nsXPTType::T_I16: value = s->val.i16; break; + case nsXPTType::T_I32: value = s->val.i32; break; + case nsXPTType::T_I64: value = s->val.i64; break; + case nsXPTType::T_U8: value = s->val.u8; break; + case nsXPTType::T_U16: value = s->val.u16; break; + case nsXPTType::T_U32: value = s->val.u32; break; + case nsXPTType::T_U64: value = s->val.u64; break; + case nsXPTType::T_BOOL: value = s->val.b; break; + case nsXPTType::T_CHAR: value = s->val.c; break; + case nsXPTType::T_WCHAR: value = s->val.wc; break; + default: value = (uint64_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + fpregs[nr_fpr++] = s->val.d; + else { + *((double *)d) = s->val.d; + d++; + } + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + fpregs[nr_fpr++] = s->val.d; + else { + *((float *)d) = s->val.f; + d++; + } + } + else { + if (nr_gpr < GPR_COUNT) + gpregs[nr_gpr++] = value; + else + *d++ = value; + } + } +} + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant * params) +{ + uint32_t nr_gpr, nr_fpr, nr_stack; + invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack); + + // Stack, if used, must be 16-bytes aligned + if (nr_stack) + nr_stack = (nr_stack + 1) & ~1; + + // Load parameters to stack, if necessary + uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8); + uint64_t gpregs[GPR_COUNT]; + double fpregs[FPR_COUNT]; + invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs); + + switch (nr_fpr) { + case 8: asm("movupd %0, %xmm7" : : "xmm7" (fpregs[7])); + case 7: asm("movupd %0, %xmm6" : : "xmm6" (fpregs[6])); + case 6: asm("movupd %0, %xmm5" : : "xmm5" (fpregs[5])); + case 5: asm("movupd %0, %xmm4" : : "xmm4" (fpregs[4])); + case 4: asm("movupd %0, %xmm3" : : "xmm3" (fpregs[3])); + case 3: asm("movupd %0, %xmm2" : : "xmm2" (fpregs[2])); + case 2: asm("movupd %0, %xmm1" : : "xmm1" (fpregs[1])); + case 1: asm("movupd %0, %xmm0" : : "xmm0" (fpregs[0])); + case 0:; + } + + // Ensure that assignments to SSE registers won't be optimized away + asm("" ::: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"); + + // Get pointer to method + uint64_t methodAddress = *((uint64_t *)that); + methodAddress += 16 + 8 * methodIndex; + methodAddress = *((uint64_t *)methodAddress); + + typedef uint32_t (*Method)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); + uint32_t result = ((Method)methodAddress)((uint64_t)that, gpregs[1], gpregs[2], gpregs[3], gpregs[4], gpregs[5]); + return result; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp new file mode 100644 index 000000000..08e519889 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp @@ -0,0 +1,188 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +#include "xptcprivate.h" + +// 6 integral parameters are passed in registers +const uint32_t GPR_COUNT = 6; + +// 8 floating point parameters are passed in SSE registers +const uint32_t FPR_COUNT = 8; + +// Remember that these 'words' are 64-bit long +static inline void +invoke_count_words(uint32_t paramCount, nsXPTCVariant * s, + uint32_t & nr_stack) +{ + uint32_t nr_gpr; + uint32_t nr_fpr; + nr_gpr = 1; // skip one GP register for 'that' + nr_fpr = 0; + nr_stack = 0; + + /* Compute number of eightbytes of class MEMORY. */ + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (!s->IsPtrData() + && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) { + if (nr_fpr < FPR_COUNT) + nr_fpr++; + else + nr_stack++; + } + else { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + nr_stack++; + } + } +} + +static void +invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s, + uint64_t * gpregs, double * fpregs) +{ + uint32_t nr_gpr = 1u; // skip one GP register for 'that' + uint32_t nr_fpr = 0u; + uint64_t value = 0u; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsPtrData()) + value = (uint64_t) s->ptr; + else { + switch (s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: value = s->val.i8; break; + case nsXPTType::T_I16: value = s->val.i16; break; + case nsXPTType::T_I32: value = s->val.i32; break; + case nsXPTType::T_I64: value = s->val.i64; break; + case nsXPTType::T_U8: value = s->val.u8; break; + case nsXPTType::T_U16: value = s->val.u16; break; + case nsXPTType::T_U32: value = s->val.u32; break; + case nsXPTType::T_U64: value = s->val.u64; break; + case nsXPTType::T_BOOL: value = s->val.b; break; + case nsXPTType::T_CHAR: value = s->val.c; break; + case nsXPTType::T_WCHAR: value = s->val.wc; break; + default: value = (uint64_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + fpregs[nr_fpr++] = s->val.d; + else { + *((double *)d) = s->val.d; + d++; + } + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + fpregs[nr_fpr++] = s->val.d; + else { + *((float *)d) = s->val.f; + d++; + } + } + else { + if (nr_gpr < GPR_COUNT) + gpregs[nr_gpr++] = value; + else + *d++ = value; + } + } +} + +// Disable avx for the next function to allow compilation with +// -march=native on new machines, or similar hardcoded -march options. +// Having avx enabled appears to change the alignment behavior of alloca +// (apparently adding an extra 16 bytes) of padding/alignment (and using +// 32-byte alignment instead of 16-byte). This seems to be the best +// available workaround, given that this code, which should perhaps +// better be written in assembly, is written in C++. +#ifndef __clang__ +#pragma GCC push_options +#pragma GCC target ("no-avx") +#endif + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_BLACKLIST +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant * params) +{ + uint32_t nr_stack; + invoke_count_words(paramCount, params, nr_stack); + + // Stack, if used, must be 16-bytes aligned + if (nr_stack) + nr_stack = (nr_stack + 1) & ~1; + + // Load parameters to stack, if necessary + uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8); + uint64_t gpregs[GPR_COUNT]; + double fpregs[FPR_COUNT]; + invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs); + + // We used to have switches to make sure we would only load the registers + // that are needed for this call. That produced larger code that was + // not faster in practice. It also caused compiler warnings about the + // variables being used uninitialized. + // We now just load every every register. There could still be a warning + // from a memory analysis tools that we are loading uninitialized stack + // positions. + + // FIXME: this function depends on the above __builtin_alloca placing + // the array in the correct spot for the ABI. + + // Load FPR registers from fpregs[] + double d0, d1, d2, d3, d4, d5, d6, d7; + + d7 = fpregs[7]; + d6 = fpregs[6]; + d5 = fpregs[5]; + d4 = fpregs[4]; + d3 = fpregs[3]; + d2 = fpregs[2]; + d1 = fpregs[1]; + d0 = fpregs[0]; + + // Load GPR registers from gpregs[] + uint64_t a0, a1, a2, a3, a4, a5; + + a5 = gpregs[5]; + a4 = gpregs[4]; + a3 = gpregs[3]; + a2 = gpregs[2]; + a1 = gpregs[1]; + a0 = (uint64_t) that; + + // Get pointer to method + uint64_t methodAddress = *((uint64_t *)that); + methodAddress += 8 * methodIndex; + methodAddress = *((uint64_t *)methodAddress); + + typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, double, double, double, + double, double, double, double, double); + nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5, + d0, d1, d2, d3, d4, d5, + d6, d7); + return result; +} + +#ifndef __clang__ +#pragma GCC pop_options +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp new file mode 100644 index 000000000..f545fcc99 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +extern "C" { + +// Remember that these 'words' are 32bit DWORDS + +uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + result++; + switch(s->type) + { + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : + result++; + break; + } + } + return result; +} + +void +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d) +{ + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + +/* XXX: the following line is here (rather than as the default clause in + * the following switch statement) so that the Sun native compiler + * will generate the correct assembly code on the Solaris Intel + * platform. See the comments in bug #28817 for more details. + */ + + *((void**)d) = s->val.p; + + switch(s->type) + { + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + } + } +} + +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp new file mode 100644 index 000000000..571fb42a2 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp @@ -0,0 +1,219 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#ifndef __AARCH64EL__ +#error "Only little endian compatibility was tested" +#endif + +/* + * This is for AArch64 ABI + * + * When we're called, the "gp" registers are stored in gprData and + * the "fp" registers are stored in fprData. Each array has 8 regs + * but first reg in gprData is a placeholder for 'self'. + */ +extern "C" nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, + uint64_t *gprData, double *fprData) +{ +#define PARAM_BUFFER_COUNT 16 +#define PARAM_GPR_COUNT 8 +#define PARAM_FPR_COUNT 8 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = NULL; + const nsXPTMethodInfo* info; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + uint32_t paramCount = info->GetParamCount(); + + // setup variant array pointer + if (paramCount > PARAM_BUFFER_COUNT) { + dispatchParams = new nsXPTCMiniVariant[paramCount]; + } else { + dispatchParams = paramBuffer; + } + NS_ASSERTION(dispatchParams,"no place for params"); + + uint64_t* ap = args; + uint32_t next_gpr = 1; // skip first arg which is 'self' + uint32_t next_fpr = 0; + for (uint32_t i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (param.IsOut() || !type.IsArithmetic()) { + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.p = (void*)gprData[next_gpr++]; + } else { + dp->val.p = (void*)*ap++; + } + continue; + } + + switch (type) { + case nsXPTType::T_I8: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i8 = (int8_t)gprData[next_gpr++]; + } else { + dp->val.i8 = (int8_t)*ap++; + } + break; + + case nsXPTType::T_I16: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i16 = (int16_t)gprData[next_gpr++]; + } else { + dp->val.i16 = (int16_t)*ap++; + } + break; + + case nsXPTType::T_I32: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i32 = (int32_t)gprData[next_gpr++]; + } else { + dp->val.i32 = (int32_t)*ap++; + } + break; + + case nsXPTType::T_I64: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i64 = (int64_t)gprData[next_gpr++]; + } else { + dp->val.i64 = (int64_t)*ap++; + } + break; + + case nsXPTType::T_U8: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u8 = (uint8_t)gprData[next_gpr++]; + } else { + dp->val.u8 = (uint8_t)*ap++; + } + break; + + case nsXPTType::T_U16: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u16 = (uint16_t)gprData[next_gpr++]; + } else { + dp->val.u16 = (uint16_t)*ap++; + } + break; + + case nsXPTType::T_U32: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u32 = (uint32_t)gprData[next_gpr++]; + } else { + dp->val.u32 = (uint32_t)*ap++; + } + break; + + case nsXPTType::T_U64: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u64 = (uint64_t)gprData[next_gpr++]; + } else { + dp->val.u64 = (uint64_t)*ap++; + } + break; + + case nsXPTType::T_FLOAT: + if (next_fpr < PARAM_FPR_COUNT) { + memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f)); + } else { + memcpy(&dp->val.f, ap++, sizeof(dp->val.f)); + } + break; + + case nsXPTType::T_DOUBLE: + if (next_fpr < PARAM_FPR_COUNT) { + memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d)); + } else { + memcpy(&dp->val.d, ap++, sizeof(dp->val.d)); + } + break; + + case nsXPTType::T_BOOL: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.b = (bool)gprData[next_gpr++]; + } else { + dp->val.b = (bool)*ap++; + } + break; + + case nsXPTType::T_CHAR: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.c = (char)gprData[next_gpr++]; + } else { + dp->val.c = (char)*ap++; + } + break; + + case nsXPTType::T_WCHAR: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.wc = (wchar_t)gprData[next_gpr++]; + } else { + dp->val.wc = (wchar_t)*ap++; + } + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if (dispatchParams != paramBuffer) { + delete [] dispatchParams; + } + + return result; +} + +// Load w17 with the constant 'n' and branch to SharedStub(). +# define STUB_ENTRY(n) \ + __asm__ ( \ + ".section \".text\" \n\t" \ + ".align 2\n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + "mov w17,#"#n" \n\t" \ + "b SharedStub \n" \ +); + +#define SENTINEL_ENTRY(n) \ + nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp new file mode 100644 index 000000000..d538767e1 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp @@ -0,0 +1,189 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +__asm__("PrepareAndDispatch") ATTRIBUTE_USED; + +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +{ + const uint8_t PARAM_BUFFER_COUNT = 16; + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + // args[0] to args[NUM_ARG_REGS] hold floating point register values + uint64_t* ap = args + NUM_ARG_REGS; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break; + case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break; + case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break; + case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break; + case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break; + case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break; + case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break; + case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // floats passed via registers are stored as doubles + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (uint64_t) args[i]; + dp->val.f = (float) dp->val.d; // convert double to float + } + else + dp->val.u32 = (uint32_t) *ap; + break; + case nsXPTType::T_DOUBLE : + // doubles passed via registers are also stored + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap; + break; + case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break; + case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break; + case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +/* + * SharedStub() + * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is + * passed to this function via $1 to preserve the argument registers. + */ +__asm__( + "#### SharedStub ####\n" +".text\n\t" + ".align 5\n\t" + ".ent SharedStub\n" +"SharedStub:\n\t" + ".frame $30,96,$26,0\n\t" + ".mask 0x4000000,-96\n\t" + "ldgp $29,0($27)\n" +"$SharedStub..ng:\n\t" + "subq $30,96,$30\n\t" + "stq $26,0($30)\n\t" + ".prologue 1\n\t" + + /* + * Store arguments passed via registers to the stack. + * Floating point registers are stored as doubles and converted + * to floats in PrepareAndDispatch if necessary. + */ + "stt $f17,16($30)\n\t" /* floating point registers */ + "stt $f18,24($30)\n\t" + "stt $f19,32($30)\n\t" + "stt $f20,40($30)\n\t" + "stt $f21,48($30)\n\t" + "stq $17,56($30)\n\t" /* integer registers */ + "stq $18,64($30)\n\t" + "stq $19,72($30)\n\t" + "stq $20,80($30)\n\t" + "stq $21,88($30)\n\t" + + /* + * Call PrepareAndDispatch function. + */ + "bis $1,$1,$17\n\t" /* pass "methodIndex" */ + "addq $30,16,$18\n\t" /* pass "args" */ + "bsr $26,$PrepareAndDispatch..ng\n\t" + + "ldq $26,0($30)\n\t" + "addq $30,96,$30\n\t" + "ret $31,($26),1\n\t" + ".end SharedStub" + ); + +/* + * nsresult nsXPTCStubBase::Stub##n() + * Sets register $1 to "methodIndex" and jumps to SharedStub. + */ +#define STUB_MANGLED_ENTRY(n, symbol) \ + "#### Stub"#n" ####" "\n\t" \ + ".text" "\n\t" \ + ".align 5" "\n\t" \ + ".globl " symbol "\n\t" \ + ".ent " symbol "\n" \ +symbol ":" "\n\t" \ + ".frame $30,0,$26,0" "\n\t" \ + "ldgp $29,0($27)" "\n" \ +"$" symbol "..ng:" "\n\t" \ + ".prologue 1" "\n\t" \ + "lda $1,"#n "\n\t" \ + "br $31,$SharedStub..ng" "\n\t" \ + ".end " symbol + +#define STUB_ENTRY(n) \ +__asm__( \ + ".if "#n" < 10" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 100" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 1000" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \ + ".else" "\n\t" \ + ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \ + ".endif" \ + ); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp new file mode 100644 index 000000000..ef4f8514d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp @@ -0,0 +1,238 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if !defined(__arm__) && !(defined(LINUX) || defined(ANDROID) || defined(XP_DARWIN)) +#error "This code is for Linux/iOS ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour." +#endif + +/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */ +static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) asm("_PrepareAndDispatch") +ATTRIBUTE_USED; + +#ifdef __ARM_EABI__ +#define DOUBLEWORD_ALIGN(p) ((uint32_t *)((((uint32_t)(p)) + 7) & 0xfffffff8)) +#else +#define DOUBLEWORD_ALIGN(p) (p) +#endif + +// Apple's iOS toolchain is lame. +#ifdef __APPLE__ +#define GNU(str) +#define APPLE(str) str +#define UNDERSCORE "__" +#else +#define GNU(str) str +#define APPLE(str) +#define UNDERSCORE "_" +#endif + +#ifdef __thumb__ +#define THUMB_FUNC ".thumb_func\n" +#else +#define THUMB_FUNC +#endif + +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : ap = DOUBLEWORD_ALIGN(ap); + dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : ap = DOUBLEWORD_ALIGN(ap); + dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : ap = DOUBLEWORD_ALIGN(ap); + dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +/* + * This is our shared stub. + * + * r0 = Self. + * + * The Rules: + * We pass an (undefined) number of arguments into this function. + * The first 3 C++ arguments are in r1 - r3, the rest are built + * by the calling function on the stack. + * + * We are allowed to corrupt r0 - r3, ip, and lr. + * + * Other Info: + * We pass the stub number in using `ip'. + * + * Implementation: + * - We save r1 to r3 inclusive onto the stack, which will be + * immediately below the caller saved arguments. + * - setup r2 (PrepareAndDispatch's args pointer) to point at + * the base of all these arguments + * - Save LR (for the return address) + * - Set r1 (PrepareAndDispatch's methodindex argument) from ip + * - r0 is passed through (self) + * - Call PrepareAndDispatch + * - When the call returns, we return by loading the PC off the + * stack, and undoing the stack (one instruction)! + * + */ +__asm__ ("\n" + GNU(".text\n") + APPLE(".section __TEXT,__text\n") + THUMB_FUNC + ".align 2\n" + "SharedStub:\n" + GNU(".fnstart\n") + GNU(".cfi_startproc\n") + "stmfd sp!, {r1, r2, r3}\n" + GNU(".save {r1, r2, r3}\n") + GNU(".cfi_def_cfa_offset 12\n") + GNU(".cfi_offset r3, -4\n") + GNU(".cfi_offset r2, -8\n") + GNU(".cfi_offset r1, -12\n") + "mov r2, sp\n" + "str lr, [sp, #-4]!\n" + GNU(".save {lr}\n") + GNU(".cfi_def_cfa_offset 16\n") + GNU(".cfi_offset lr, -16\n") + "mov r1, ip\n" + "bl _PrepareAndDispatch\n" + "ldr pc, [sp], #16\n" + GNU(".cfi_endproc\n") + GNU(".fnend")); + +/* + * Create sets of stubs to call the SharedStub. + * We don't touch the stack here, nor any registers, other than IP. + * IP is defined to be corruptable by a called function, so we are + * safe to use it. + * + * This will work with or without optimisation. + */ + +/* + * Note : As G++3 ABI contains the length of the functionname in the + * mangled name, it is difficult to get a generic assembler mechanism like + * in the G++ 2.95 case. + * Create names would be like : + * _ZN14nsXPTCStubBase5Stub9Ev + * _ZN14nsXPTCStubBase6Stub13Ev + * _ZN14nsXPTCStubBase7Stub144Ev + * Use the assembler directives to get the names right... + */ + +#define STUB_ENTRY(n) \ + __asm__( \ + GNU(".section \".text\"\n") \ + APPLE(".section __TEXT,__text\n") \ +" .align 2\n" \ +" .if ("#n" - 10) < 0\n" \ +" .globl " UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev\n" \ + THUMB_FUNC \ + GNU(".type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n") \ +UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \ +" .else\n" \ +" .if ("#n" - 100) < 0\n" \ +" .globl " UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev\n" \ + THUMB_FUNC \ + GNU(".type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n") \ +UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \ +" .else\n" \ +" .if ("#n" - 1000) < 0\n" \ +" .globl " UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev\n" \ + THUMB_FUNC \ + GNU(".type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n") \ +UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \ +" .else\n" \ +" .err \"stub number "#n"> 1000 not yet supported\"\n" \ +" .endif\n" \ +" .endif\n" \ +" .endif\n" \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); + +#if 0 +/* + * This part is left in as comment : this is how the method definition + * should look like. + */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n () \ +{ \ + __asm__ ( \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); \ + return 0; /* avoid warnings */ \ +} +#endif + + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp new file mode 100644 index 000000000..27c2b3d02 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp @@ -0,0 +1,113 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + nsIInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + NS_RELEASE(iface_info); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +/* + * These stubs move just move the values passed in registers onto the stack, + * so they are contiguous with values passed on the stack, and then calls + * PrepareAndDispatch() to do the dirty work. + */ + +#define STUB_ENTRY(n) \ +__asm__( \ + ".global _Stub"#n"__14nsXPTCStubBase\n\t" \ +"_Stub"#n"__14nsXPTCStubBase:\n\t" \ + "stmfd sp!, {r1, r2, r3} \n\t" \ + "mov ip, sp \n\t" \ + "stmfd sp!, {fp, ip, lr, pc} \n\t" \ + "sub fp, ip, #4 \n\t" \ + "mov r1, #"#n" \n\t" /* = methodIndex */ \ + "add r2, sp, #16 \n\t" \ + "bl _PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi \n\t" \ + "ldmea fp, {fp, sp, lr} \n\t" \ + "add sp, sp, #12 \n\t" \ + "mov pc, lr \n\t" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp new file mode 100644 index 000000000..f63d0c1e2 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp @@ -0,0 +1,205 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#ifdef __GNUC__ +/* This tells gcc3.4+ not to optimize away symbols. + * @see http://gcc.gnu.org/gcc-3.4/changes.html + */ +#define DONT_DROP_OR_WARN __attribute__((used)) +#else +/* This tells older gccs not to warn about unused vairables. + * @see http://docs.freebsd.org/info/gcc/gcc.info.Variable_Attributes.html + */ +#define DONT_DROP_OR_WARN __attribute__((unused)) +#endif + +/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */ +static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) asm("_PrepareAndDispatch") +DONT_DROP_OR_WARN; + +static nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +/* + * This is our shared stub. + * + * r0 = Self. + * + * The Rules: + * We pass an (undefined) number of arguments into this function. + * The first 3 C++ arguments are in r1 - r3, the rest are built + * by the calling function on the stack. + * + * We are allowed to corrupt r0 - r3, ip, and lr. + * + * Other Info: + * We pass the stub number in using `ip'. + * + * Implementation: + * - We save r1 to r3 inclusive onto the stack, which will be + * immediately below the caller saved arguments. + * - setup r2 (PrepareAndDispatch's args pointer) to point at + * the base of all these arguments + * - Save LR (for the return address) + * - Set r1 (PrepareAndDispatch's methodindex argument) from ip + * - r0 is passed through (self) + * - Call PrepareAndDispatch + * - When the call returns, we return by loading the PC off the + * stack, and undoing the stack (one instruction)! + * + */ +__asm__ ("\n\ + .text \n\ + .align 2 \n\ +SharedStub: \n\ + stmfd sp!, {r1, r2, r3} \n\ + mov r2, sp \n\ + str lr, [sp, #-4]! \n\ + mov r1, ip \n\ + bl _PrepareAndDispatch \n\ + ldr pc, [sp], #16"); + +/* + * Create sets of stubs to call the SharedStub. + * We don't touch the stack here, nor any registers, other than IP. + * IP is defined to be corruptable by a called function, so we are + * safe to use it. + * + * This will work with or without optimisation. + */ + +/* + * Note : As G++3 ABI contains the length of the functionname in the + * mangled name, it is difficult to get a generic assembler mechanism like + * in the G++ 2.95 case. + * Create names would be like : + * _ZN14nsXPTCStubBase5Stub9Ev + * _ZN14nsXPTCStubBase6Stub13Ev + * _ZN14nsXPTCStubBase7Stub144Ev + * Use the assembler directives to get the names right... + */ + +#define STUB_ENTRY(n) \ + __asm__( \ + ".section \".text\"\n" \ +" .align 2\n" \ +" .iflt ("#n" - 10)\n" \ +" .globl _ZN14nsXPTCStubBase5Stub"#n"Ev\n" \ +" .type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \ +" .else\n" \ +" .iflt ("#n" - 100)\n" \ +" .globl _ZN14nsXPTCStubBase6Stub"#n"Ev\n" \ +" .type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \ +" .else\n" \ +" .iflt ("#n" - 1000)\n" \ +" .globl _ZN14nsXPTCStubBase7Stub"#n"Ev\n" \ +" .type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \ +" .else\n" \ +" .err \"stub number "#n"> 1000 not yet supported\"\n" \ +" .endif\n" \ +" .endif\n" \ +" .endif\n" \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); + +#if 0 +/* + * This part is left in as comment : this is how the method definition + * should look like. + */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n () \ +{ \ + __asm__ ( \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); \ + return 0; /* avoid warnings */ \ +} +#endif + + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s new file mode 100644 index 000000000..6603a4f25 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s @@ -0,0 +1,39 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + .set NGPREGS,8 + .set NFPREGS,8 + + .section ".text" + .globl SharedStub + .hidden SharedStub + .type SharedStub,@function +SharedStub: + stp x29, x30, [sp,#-16]! + mov x29, sp + + sub sp, sp, #8*(NGPREGS+NFPREGS) + stp x0, x1, [sp, #64+(0*8)] + stp x2, x3, [sp, #64+(2*8)] + stp x4, x5, [sp, #64+(4*8)] + stp x6, x7, [sp, #64+(6*8)] + stp d0, d1, [sp, #(0*8)] + stp d2, d3, [sp, #(2*8)] + stp d4, d5, [sp, #(4*8)] + stp d6, d7, [sp, #(6*8)] + + # methodIndex passed from stub + mov w1, w17 + + add x2, sp, #16+(8*(NGPREGS+NFPREGS)) + add x3, sp, #8*NFPREGS + add x4, sp, #0 + + bl PrepareAndDispatch + + add sp, sp, #8*(NGPREGS+NFPREGS) + ldp x29, x30, [sp],#16 + ret + + .size SharedStub, . - SharedStub diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s new file mode 100644 index 000000000..720dd6cc7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s @@ -0,0 +1,123 @@ + +// Select C numeric constant + .radix C + .psr abi32 + .psr msb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'SharedStub' + .proc SharedStub +// manual bundling + .explicit + + .global PrepareAndDispatch +// .exclass PrepareAndDispatch, @fullyvisible + .type PrepareAndDispatch,@function + +SharedStub:: +// 10 arguments, first 8 are the input arguments of previous +// function call. The 9th one is methodIndex and the 10th is the +// pointer to the remaining input arguments. The last two arguments +// are passed in memory. + .prologue + .save ar.pfs , r41 +// allocate 8 input args, 4 local args, and 5 output args + alloc r41 = ar.pfs, 8, 4, 5, 0 // M + .save rp, r40 + mov r40 = rp // I + addp4 out4 = 28, sp ;; // I + + .save ar.unat, r42 + mov r42 = ar.unat // M + .fframe 144 + add sp = -144, sp // A +// unwind table already knows gp, don't need to specify anything + add r43 = 0, gp ;; // A + +// We have possible 8 integer registers and 8 float registers that could +// be arguments. We also have a stack region from the previous +// stack frame that may hold some stack arguments. +// We need to write the integer registers to a memory region, write +// the float registers to a memory region (making sure we don't step +// on NAT while touching the registers). We also mark the memory +// address of the stack arguments. +// We then call PrepareAndDispatch() specifying the three memory +// region pointers. + + + .body + add out0 = 0, in0 // A move self ptr +// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space +// methodIndex is at 144 + 16 bytes away from current sp +// (current frame + previous frame header) + ld4 out4 = [out4] // A restarg address + add r11 = 160, sp ;; // A address of methodIndex + + ld8 out1 = [r11] // M load methodIndex +// sp + 16 is the start of intargs + add out2 = 16, sp // A address of intargs +// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs + add out3 = 80, sp ;; // A address of floatargs + + add r11 = 0, out2 ;; // A + st8.spill [r11] = in1, 8 // M + add r10 = 0, out3 ;; // A + + st8.spill [r11] = in2, 8 ;; // M + st8.spill [r11] = in3, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in4, 8 ;; // M + st8.spill [r11] = in5, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in6, 8 ;; // M + st8.spill [r11] = in7 // M + fclass.nm p14,p15 = f8,@nat ;; // F + +(p14) stfd [r10] = f8, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 = f9,@nat ;; // F + +(p12) stfd [r10] = f9, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f10,@nat ;; // F + +(p14) stfd [r10] = f10, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f11,@nat ;; // F + +(p12) stfd [r10] = f11, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f12,@nat ;; // F + +(p14) stfd [r10] = f12, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f13,@nat ;; // F + +(p12) stfd [r10] = f13, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f14,@nat ;; // F + +(p14) stfd [r10] = f14, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f15,@nat ;; // F + +(p12) stfd [r10] = f15, 8 // M +(p13) add r10 = 8, r10 // A + +// branch to PrepareAndDispatch + br.call.dptk.few rp = PrepareAndDispatch ;; // B + +// epilog + mov ar.unat = r42 // M + mov ar.pfs = r41 // I + mov rp = r40 ;; // I + + add gp = 0, r43 // A + add sp = 144, sp // A + br.ret.dptk.few rp ;; // B + + .endp + + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s new file mode 100644 index 000000000..4c07836d7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s @@ -0,0 +1,124 @@ + +// Select C numeric constant + .radix C + .psr abi64 + .psr lsb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'SharedStub' + .proc SharedStub +// manual bundling + .explicit + + .global PrepareAndDispatch +// .exclass PrepareAndDispatch, @fullyvisible + .type PrepareAndDispatch,@function + +SharedStub:: +// 10 arguments, first 8 are the input arguments of previous +// function call. The 9th one is methodIndex and the 10th is the +// pointer to the remaining input arguments. The last two arguments +// are passed in memory. + .prologue + .save ar.pfs , r41 +// allocate 8 input args, 4 local args, and 5 output args + alloc r41 = ar.pfs, 8, 4, 5, 0 // M + .save rp, r40 + mov r40 = rp // I + add out4 = 24, sp ;; // I + + .save ar.unat, r42 + mov r42 = ar.unat // M + .fframe 144 + add sp = -144, sp // A +// unwind table already knows gp, don't need to specify anything + add r43 = 0, gp ;; // A + +// We have possible 8 integer registers and 8 float registers that could +// be arguments. We also have a stack region from the previous +// stack frame that may hold some stack arguments. +// We need to write the integer registers to a memory region, write +// the float registers to a memory region (making sure we don't step +// on NAT while touching the registers). We also mark the memory +// address of the stack arguments. +// We then call PrepareAndDispatch() specifying the three memory +// region pointers. + + + .body + add out0 = 0, in0 // A move self ptr +// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space +// methodIndex is at 144 + 16 bytes away from current sp +// (current frame + previous frame header) + ld8 out4 = [out4] // M restarg address + add r11 = 160, sp ;; // A address of methodIndex + + ld8 out1 = [r11] // M load methodIndex +// sp + 16 is the start of intargs + add out2 = 16, sp // A address of intargs +// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs + add out3 = 80, sp ;; // A address of floatargs + + add r11 = 0, out2 ;; // A + st8.spill [r11] = in1, 8 // M + add r10 = 0, out3 ;; // A + + st8.spill [r11] = in2, 8 ;; // M + st8.spill [r11] = in3, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in4, 8 ;; // M + st8.spill [r11] = in5, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in6, 8 ;; // M + st8.spill [r11] = in7 // M + fclass.nm p14,p15 = f8,@nat ;; // F + +(p14) stfd [r10] = f8, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 = f9,@nat ;; // F + +(p12) stfd [r10] = f9, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f10,@nat ;; // F + +(p14) stfd [r10] = f10, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f11,@nat ;; // F + +(p12) stfd [r10] = f11, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f12,@nat ;; // F + +(p14) stfd [r10] = f12, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f13,@nat ;; // F + +(p12) stfd [r10] = f13, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f14,@nat ;; // F + +(p14) stfd [r10] = f14, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f15,@nat ;; // F + +(p12) stfd [r10] = f15, 8 // M +(p13) add r10 = 8, r10 // A + +// branch to PrepareAndDispatch + br.call.dptk.few rp = PrepareAndDispatch ;; // B + +// epilog + mov ar.unat = r42 // M + mov ar.pfs = r41 // I + mov rp = r40 ;; // I + + add gp = 0, r43 // A + add sp = 144, sp // A + br.ret.dptk.few rp ;; // B + + .endp + +/* Magic indicating no need for an executable stack */ +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S new file mode 100644 index 000000000..d17301634 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S @@ -0,0 +1,116 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +#ifdef ANDROID +#include <asm/regdef.h> +#include <asm/asm.h> +#include <machine/asm.h> +#else +#include <sys/regdef.h> +#include <sys/asm.h> +#endif + +# NARGSAVE is the argument space in the callers frame, including extra +# 'shadowed' space for the argument registers. The minimum of 4 +# argument slots is sometimes predefined in the header files. +#ifndef NARGSAVE +#define NARGSAVE 4 +#endif + +#define LOCALSZ 2 /* gp, ra */ +#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK) + +#define RAOFF (FRAMESZ - (1*SZREG)) +#define GPOFF (FRAMESZ - (2*SZREG)) + +#define A0OFF (FRAMESZ + (0*SZREG)) +#define A1OFF (FRAMESZ + (1*SZREG)) +#define A2OFF (FRAMESZ + (2*SZREG)) +#define A3OFF (FRAMESZ + (3*SZREG)) + + .text + +#define STUB_ENTRY(x) \ + .if x < 10; \ + .globl _ZN14nsXPTCStubBase5Stub ##x ##Ev; \ + .type _ZN14nsXPTCStubBase5Stub ##x ##Ev,@function; \ + .aent _ZN14nsXPTCStubBase5Stub ##x ##Ev,0; \ +_ZN14nsXPTCStubBase5Stub ##x ##Ev:; \ + SETUP_GP; \ + li t0,x; \ + b sharedstub; \ + .elseif x < 100; \ + .globl _ZN14nsXPTCStubBase6Stub ##x ##Ev; \ + .type _ZN14nsXPTCStubBase6Stub ##x ##Ev,@function; \ + .aent _ZN14nsXPTCStubBase6Stub ##x ##Ev,0; \ +_ZN14nsXPTCStubBase6Stub ##x ##Ev:; \ + SETUP_GP; \ + li t0,x; \ + b sharedstub; \ + .elseif x < 1000; \ + .globl _ZN14nsXPTCStubBase7Stub ##x ##Ev; \ + .type _ZN14nsXPTCStubBase7Stub ##x ##Ev,@function; \ + .aent _ZN14nsXPTCStubBase7Stub ##x ##Ev,0; \ +_ZN14nsXPTCStubBase7Stub ##x ##Ev:; \ + SETUP_GP; \ + li t0,x; \ + b sharedstub; \ + .else; \ + .err; \ + .endif + +# SENTINEL_ENTRY is handled in the cpp file. +#define SENTINEL_ENTRY(x) + +# +# open a dummy frame for the function entries +# + .align 2 + .type dummy,@function + .ent dummy, 0 + .frame sp, FRAMESZ, ra +dummy: + SETUP_GP + +#include "xptcstubsdef.inc" + +sharedstub: + subu sp, FRAMESZ + + # specify the save register mask for gp, ra, a0-a3 + .mask 0x900000F0, RAOFF-FRAMESZ + + sw ra, RAOFF(sp) + SAVE_GP(GPOFF) + + # Micro-optimization: a0 is already loaded, and its slot gets + # ignored by PrepareAndDispatch, so no need to save it here. + # sw a0, A0OFF(sp) + sw a1, A1OFF(sp) + sw a2, A2OFF(sp) + sw a3, A3OFF(sp) + + la t9, PrepareAndDispatch + + # t0 is methodIndex + move a1, t0 + # have a2 point to the begin of the argument space on stack + addiu a2, sp, FRAMESZ + + # PrepareAndDispatch(that, methodIndex, args) + jalr t9 + + # Micro-optimization: Using jalr explicitly has the side-effect + # of not triggering .cprestore. This is ok because we have no + # gp reference below this point. It also allows better + # instruction sscheduling. + # lw gp, GPOFF(fp) + + lw ra, RAOFF(sp) + addiu sp, FRAMESZ + j ra + END(dummy) diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 new file mode 100644 index 000000000..33c7b1492 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 @@ -0,0 +1,75 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +#include <sys/regdef.h> +#include <sys/asm.h> + + .text + .globl PrepareAndDispatch + +NARGSAVE=4 # extra space for the callee to use. gccism + # we can put our a0-a3 in our callers space. +LOCALSZ=2 # gp, ra +FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK + +define(STUB_NAME, `Stub'$1`__14nsXPTCStubBase') + +define(STUB_ENTRY, +` .globl 'STUB_NAME($1)` + .align 2 + .type 'STUB_NAME($1)`,@function + .ent 'STUB_NAME($1)`, 0 +'STUB_NAME($1)`: + .frame sp, FRAMESZ, ra + .set noreorder + .cpload t9 + .set reorder + subu sp, FRAMESZ + .cprestore 16 + li t0, '$1` + b sharedstub +.end 'STUB_NAME($1)` + +') + +define(SENTINEL_ENTRY, `') + +include(xptcstubsdef.inc) + + .globl sharedstub + .ent sharedstub +sharedstub: + + REG_S ra, 20(sp) + + REG_S a0, 24(sp) + REG_S a1, 28(sp) + REG_S a2, 32(sp) + REG_S a3, 36(sp) + + # t0 is methodIndex + move a1, t0 + + # put the start of a1, a2, a3, and stack + move a2, sp + addi a2, 24 # have a2 point to sp + 24 (where a0 is) + + # PrepareAndDispatch(that, methodIndex, args) + # a0 a1 a2 + # + jal PrepareAndDispatch + + REG_L ra, 20(sp) + REG_L a1, 28(sp) + REG_L a2, 32(sp) + + addu sp, FRAMESZ + j ra + +.end sharedstub diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S new file mode 100644 index 000000000..11d851536 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S @@ -0,0 +1,111 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <sys/regdef.h> +#include <sys/asm.h> + +LOCALSZ=16 +FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK + +A1OFF=FRAMESZ-(9*SZREG) +A2OFF=FRAMESZ-(8*SZREG) +A3OFF=FRAMESZ-(7*SZREG) +A4OFF=FRAMESZ-(6*SZREG) +A5OFF=FRAMESZ-(5*SZREG) +A6OFF=FRAMESZ-(4*SZREG) +A7OFF=FRAMESZ-(3*SZREG) +GPOFF=FRAMESZ-(2*SZREG) +RAOFF=FRAMESZ-(1*SZREG) + +F13OFF=FRAMESZ-(16*SZREG) +F14OFF=FRAMESZ-(15*SZREG) +F15OFF=FRAMESZ-(14*SZREG) +F16OFF=FRAMESZ-(13*SZREG) +F17OFF=FRAMESZ-(12*SZREG) +F18OFF=FRAMESZ-(11*SZREG) +F19OFF=FRAMESZ-(10*SZREG) + +#define SENTINEL_ENTRY(n) /* defined in cpp file, not here */ + +#define STUB_ENTRY(x) \ + .if x < 10; \ + MAKE_STUB(x, _ZN14nsXPTCStubBase5Stub ##x ##Ev); \ + .elseif x < 100; \ + MAKE_STUB(x, _ZN14nsXPTCStubBase6Stub ##x ##Ev); \ + .elseif x < 1000; \ + MAKE_STUB(x, _ZN14nsXPTCStubBase7Stub ##x ##Ev); \ + .else; \ + .err; \ + .endif + +#define MAKE_STUB(x, name) \ + .globl name; \ + .type name,@function; \ + .aent name,0; \ +name:; \ + PTR_SUBU sp,FRAMESZ; \ + SETUP_GP64(GPOFF, name); \ + li t0,x; \ + b sharedstub; \ + +# +# open a dummy frame for the function entries +# + .text + .align 2 + .type dummy,@function + .ent dummy, 0 +dummy: + .frame sp, FRAMESZ, ra + .mask 0x90000FF0, RAOFF-FRAMESZ + .fmask 0x000FF000, F19OFF-FRAMESZ + +#include "xptcstubsdef.inc" + +sharedstub: + + REG_S a1, A1OFF(sp) + REG_S a2, A2OFF(sp) + REG_S a3, A3OFF(sp) + REG_S a4, A4OFF(sp) + REG_S a5, A5OFF(sp) + REG_S a6, A6OFF(sp) + REG_S a7, A7OFF(sp) + REG_S ra, RAOFF(sp) + + s.d $f13, F13OFF(sp) + s.d $f14, F14OFF(sp) + s.d $f15, F15OFF(sp) + s.d $f16, F16OFF(sp) + s.d $f17, F17OFF(sp) + s.d $f18, F18OFF(sp) + s.d $f19, F19OFF(sp) + + # t0 is methodIndex + move a1, t0 + + # a2 is stack address where extra function params + # are stored that do not fit in registers + move a2, sp + PTR_ADDI a2, FRAMESZ + + # a3 is stack address of a1..a7 + move a3, sp + PTR_ADDI a3, A1OFF + + # a4 is stack address of f13..f19 + move a4, sp + PTR_ADDI a4, F13OFF + + # PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs) + # a0 a1 a2 a3 a4 + # + jal PrepareAndDispatch + + REG_L ra, RAOFF(sp) + RESTORE_GP64 + + PTR_ADDU sp, FRAMESZ + j ra + END(dummy) diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s new file mode 100644 index 000000000..9e86848fc --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s @@ -0,0 +1,68 @@ + .LEVEL 1.1 + +curframesz .EQU 128 +; SharedStub has stack size of 128 bytes + +lastframesz .EQU 64 +; the StubN C++ function has a small stack size of 64 bytes + + .SPACE $TEXT$,SORT=8 + .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24 +SharedStub + .PROC + .CALLINFO CALLER,FRAME=80,SAVE_RP,ARGS_SAVED + + .ENTRY + STW %rp,-20(%sp) + LDO 128(%sp),%sp + + STW %r19,-32(%r30) + STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame + + LDO -80(%r30),%r28 + FSTD,MA %fr5,8(%r28) ; save darg0 + FSTD,MA %fr7,8(%r28) ; save darg1 + FSTW,MA %fr4L,4(%r28) ; save farg0 + FSTW,MA %fr5L,4(%r28) ; save farg1 + FSTW,MA %fr6L,4(%r28) ; save farg2 + FSTW,MA %fr7L,4(%r28) ; save farg3 + + ; Former value of register 26 is already properly saved by StubN, + ; but register 25-23 are not because of the arguments mismatch + STW %r25,-40-curframesz-lastframesz(%r30) ; save r25 + STW %r24,-44-curframesz-lastframesz(%r30) ; save r24 + STW %r23,-48-curframesz-lastframesz(%r30) ; save r23 + COPY %r26,%r25 ; method index is arg1 + LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0 + LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2 + LDO -80(%r30),%r23 ; floating args is arg3 + + BL .+8,%r2 + ADDIL L'PrepareAndDispatch-$PIC_pcrel$0+4,%r2 + LDO R'PrepareAndDispatch-$PIC_pcrel$1+8(%r1),%r1 +$PIC_pcrel$0 + LDSID (%r1),%r31 +$PIC_pcrel$1 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR +;in=23-26;out=28; + BLE 0(%sr0,%r1) + COPY %r31,%r2 + + LDW -32(%r30),%r19 + + LDW -148(%sp),%rp + BVE (%rp) + .EXIT + LDO -128(%sp),%sp + + + .PROCEND ;in=26;out=28; + + .ALIGN 8 + .SPACE $TEXT$ + .SUBSPA $CODE$ + .IMPORT PrepareAndDispatch,CODE + .EXPORT SharedStub,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR,LONG_RETURN + .END + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s new file mode 100644 index 000000000..b45d7763b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s @@ -0,0 +1,73 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .LEVEL 1.1 + .TEXT + .ALIGN 4 + +curframesz: + .EQU 128 + + +; SharedStub has stack size of 128 bytes + +lastframesz: + .EQU 64 + +; the StubN C++ function has a small stack size of 64 bytes + + +.globl SharedStub + .type SharedStub, @function + +SharedStub: + .PROC + .CALLINFO CALLER,FRAME=80,SAVE_RP + + .ENTRY + STW %rp,-20(%sp) + LDO 128(%sp),%sp + + STW %r19,-32(%r30) + STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame + + LDO -80(%r30),%r28 + FSTD,MA %fr5,8(%r28) ; save darg0 + FSTD,MA %fr7,8(%r28) ; save darg1 + FSTW,MA %fr4L,4(%r28) ; save farg0 + FSTW,MA %fr5L,4(%r28) ; save farg1 + FSTW,MA %fr6L,4(%r28) ; save farg2 + FSTW,MA %fr7L,4(%r28) ; save farg3 + + ; Former value of register 26 is already properly saved by StubN, + ; but register 25-23 are not because of the argument mismatch + STW %r25,-40-curframesz-lastframesz(%r30) ; save r25 + STW %r24,-44-curframesz-lastframesz(%r30) ; save r24 + STW %r23,-48-curframesz-lastframesz(%r30) ; save r23 + COPY %r26,%r25 ; method index is arg1 + LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0 + LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2 + LDO -80(%r30),%r23 ; floating args is arg3 + + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=23-26;out=28; + BL PrepareAndDispatch, %r31 + COPY %r31,%r2 + + LDW -32(%r30),%r19 + + LDW -148(%sp),%rp + LDO -128(%sp),%sp + + + BV,N (%rp) + NOP + NOP + + .EXIT + .PROCEND ;in=26;out=28; + + .SIZE SharedStub, .-SharedStub diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S new file mode 100644 index 000000000..877e262b9 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S @@ -0,0 +1,112 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set r1,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + +#if _CALL_ELF == 2 +#define STACK_PARAMS 96 +#else +#define STACK_PARAMS 112 +#endif + +#if _CALL_ELF == 2 + .section ".text" + .type SharedStub,@function + .globl SharedStub + # Make the symbol hidden so that the branch from the stub does + # not go via a PLT. This is not only better for performance, + # but may be necessary to avoid linker errors since there is + # no place to restore the TOC register in a sibling call. + .hidden SharedStub + .align 2 +SharedStub: +0: addis 2,12,(.TOC.-0b)@ha + addi 2,2,(.TOC.-0b)@l + .localentry SharedStub,.-SharedStub +#else + .section ".text" + .align 2 + .globl SharedStub + # Make the symbol hidden so that the branch from the stub does + # not go via a PLT. This is not only better for performance, + # but may be necessary to avoid linker errors since there is + # no place to restore the TOC register in a sibling call. + .hidden SharedStub + .section ".opd","aw" + .align 3 + +SharedStub: + .quad .SharedStub,.TOC.@tocbase + .previous + .type SharedStub,@function + +.SharedStub: +#endif + mflr r0 + + std r4, -56(r1) # Save all GPRS + std r5, -48(r1) + std r6, -40(r1) + std r7, -32(r1) + std r8, -24(r1) + std r9, -16(r1) + std r10, -8(r1) + + stfd f13, -64(r1) # ... and FPRS + stfd f12, -72(r1) + stfd f11, -80(r1) + stfd f10, -88(r1) + stfd f9, -96(r1) + stfd f8, -104(r1) + stfd f7, -112(r1) + stfd f6, -120(r1) + stfd f5, -128(r1) + stfd f4, -136(r1) + stfd f3, -144(r1) + stfd f2, -152(r1) + stfd f1, -160(r1) + + subi r6,r1,56 # r6 --> gprData + subi r7,r1,160 # r7 --> fprData + addi r5,r1,STACK_PARAMS # r5 --> extra stack args + + std r0, 16(r1) + + stdu r1,-288(r1) + # r3 has the 'self' pointer + # already + + mr r4,r11 # r4 is methodIndex selector, + # passed via r11 in the + # nsNSStubBase::StubXX() call + + bl PrepareAndDispatch + nop + + ld 1,0(r1) # restore stack + ld r0,16(r1) # restore LR + mtlr r0 + blr + +#if _CALL_ELF == 2 + .size SharedStub,.-SharedStub +#else + .size SharedStub,.-.SharedStub +#endif + + # Magic indicating no need for an executable stack + .section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 new file mode 100644 index 000000000..6dabf334d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 @@ -0,0 +1,119 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + +# Define the correct name of the stub function based on the object model + +define(STUB_NAME, + ifelse(AIX_OBJMODEL, ibm, + `Stub'$1`__EI14nsXPTCStubBaseFv', + `Stub'$1`__14nsXPTCStubBaseFv')) + +define(STUB_ENTRY, ` + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`" + .csect H.10.NO_SYMBOL{PR} + .globl .'STUB_NAME($1)` + .globl 'STUB_NAME($1)`{DS} + +.'STUB_NAME($1)`: + li r12, '$1` + b .SharedStub + nop + + + .toc +T.18.'STUB_NAME($1)`: + .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS} + .csect 'STUB_NAME($1)`{DS} + .long .'STUB_NAME($1)` + .long TOC{TC0} + .long 0x00000000 +') + +define(SENTINEL_ENTRY, `') + +include(xptcstubsdef.inc) + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.SharedStub{TC},"SharedStub" + +# .text section + .csect H.10.NO_SYMBOL{PR} + .globl .SharedStub + .globl SharedStub{DS} + .extern .PrepareAndDispatch + +.SharedStub: + mflr r0 + stw r0,8(sp) + + stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28) + # outgoing params to PrepareAndDispatch (20) + + stw r4,44(sp) # link area (24) + PrepareAndDispatch params (20) + stw r5,48(sp) + stw r6,52(sp) + stw r7,56(sp) + stw r8,60(sp) + stw r9,64(sp) + stw r10,68(sp) + stfd f1,72(sp) + stfd f2,80(sp) + stfd f3,88(sp) + stfd f4,96(sp) + stfd f5,104(sp) + stfd f6,112(sp) + stfd f7,120(sp) + stfd f8,128(sp) + stfd f9,136(sp) + stfd f10,144(sp) + stfd f11,152(sp) + stfd f12,156(sp) + stfd f13,164(sp) + + addi r6,sp,44 # gprData + + addi r7,sp,72 # fprData + # r3 has the 'self' pointer already + mr r4,r12 # methodIndex selector (it is now LATER) + addi r5,sp,232 # pointer to callers args area, beyond r3-r10 + # mapped range + + bl .PrepareAndDispatch + nop + + + lwz r0,184(sp) + addi sp,sp,176 + mtlr r0 + blr + +# .data section + + .toc # 0x00000038 +T.18.SharedStub: + .tc H.18.SharedStub{TC},SharedStub{DS} + + .csect SharedStub{DS} + .long .SharedStub # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0008" + .long 0x00000000 # "\0\0\0\0" +# End csect SharedStub{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 new file mode 100644 index 000000000..24d713cc9 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 @@ -0,0 +1,97 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +# Define the correct name of the stub function based on the object model +define(STUB_NAME, + ifelse(AIX_OBJMODEL, ibm, + `Stub'$1`__EI14nsXPTCStubBaseFv', + `Stub'$1`__14nsXPTCStubBaseFv')) +define(STUB_ENTRY, ` + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`" + .csect H.10.NO_SYMBOL{PR} + .globl .'STUB_NAME($1)` + .globl 'STUB_NAME($1)`{DS} +.'STUB_NAME($1)`: + li r12, '$1` + b .SharedStub + nop + .toc +T.18.'STUB_NAME($1)`: + .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS} + .csect 'STUB_NAME($1)`{DS} + .llong .'STUB_NAME($1)` + .llong TOC{TC0} + .llong 0x00000000 +') +define(SENTINEL_ENTRY, `') +include(xptcstubsdef.inc) + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.SharedStub{TC},"SharedStub" +# .text section + .csect H.10.NO_SYMBOL{PR} + .globl .SharedStub + .globl SharedStub{DS} + .extern .PrepareAndDispatch +.SharedStub: + mflr r0 + std r0,16(sp) + stdu sp,-248(sp) # room for linkage (24*2), fprData (104), gprData(28*2) + # outgoing params to PrepareAndDispatch (40) + std r4,88(sp) # link area (48) + PrepareAndDispatch params (20) + std r5,96(sp) + std r6,104(sp) + std r7,112(sp) + std r8,120(sp) + std r9,128(sp) + std r10,136(sp) + stfd f1,144(sp) + stfd f2,152(sp) + stfd f3,160(sp) + stfd f4,168(sp) + stfd f5,176(sp) + stfd f6,184(sp) + stfd f7,192(sp) + stfd f8,200(sp) + stfd f9,208(sp) + stfd f10,216(sp) + stfd f11,224(sp) + stfd f12,232(sp) + stfd f13,240(sp) + addi r6,sp,88 # gprData + addi r7,sp,144 # fprData + # r3 has the 'self' pointer already + mr r4,r12 # methodIndex selector (it is now LATER) + addi r5,sp,360 # pointer to callers args area, beyond r3-r10 + # mapped range + bl .PrepareAndDispatch + nop + ld r0,264(sp) + addi sp,sp,248 + mtlr r0 + blr +# .data section + .toc # 0x00000038 +T.18.SharedStub: + .tc H.18.SharedStub{TC},SharedStub{DS} + .csect SharedStub{DS} + .llong .SharedStub # "\0\0\0\0" + .llong TOC{TC0} # "\0\0\0008" + .llong 0x00000000 # "\0\0\0\0" +# End csect SharedStub{DS} +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 new file mode 100644 index 000000000..dda537850 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 @@ -0,0 +1,114 @@ +/* -*- Mode: asm -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .text + .globl _SharedStub +dnl +define(STUB_MANGLED_ENTRY, +` .globl '$2` + .align 2 +'$2`: + addi r12, 0,'$1` + b _SharedStub') +dnl +define(STUB_ENTRY, +` .if '$1` < 10 +STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase5Stub'$1`Ev') + .elseif '$1` < 100 +STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase6Stub'$1`Ev') + .elseif '$1` < 1000 +STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase7Stub'$1`Ev') + .else + .err "Stub'$1` >= 1000 not yet supported." + .endif +') +dnl +define(SENTINEL_ENTRY, `') +dnl +include(xptcstubsdef.inc) +dnl +// See also xptcstubs_ppc_rhapsody.cpp:PrepareAndDispatch. +_SharedStub: + // Prolog(ue) + mflr r0 // Save the link register in the caller's + stw r0, 8(r1) // stack frame + stwu r1,-176(r1) // Allocate stack space for our own frame and + // adjust stack pointer + + // Linkage area, 0(r1) to 24(r1) + // Original sp saved at 0(r1) + + // Parameter area, 20 bytes from 24(r1) to + // 44(r1) to accomodate 5 arguments passed + // to PrepareAndDispatch + + // Local variables, 132 bytes from 44(r1) + // to 176(r1), to accomodate 5 words and + // 13 doubles + + stw r4, 44(r1) // Save parameters passed in GPRs r4-r10; + stw r5, 48(r1) // a pointer to here will be passed to + stw r6, 52(r1) // PrepareAndDispatch for access to + stw r7, 56(r1) // arguments passed in registers. r3, + stw r8, 60(r1) // the self pointer, is used for the + stw r9, 64(r1) // call but isn't otherwise needed in + stw r10, 68(r1) // PrepareAndDispatch, so it is not saved. + + stfd f1, 72(r1) // Do the same for floating-point parameters + stfd f2, 80(r1) // passed in FPRs f1-f13 + stfd f3, 88(r1) + stfd f4, 96(r1) + stfd f5, 104(r1) + stfd f6, 112(r1) + stfd f7, 120(r1) + stfd f8, 128(r1) + stfd f9, 136(r1) + stfd f10, 144(r1) + stfd f11, 152(r1) + stfd f12, 160(r1) + stfd f13, 168(r1) + + // Set up parameters for call to + // PrepareAndDispatch. argument= + // 0, pointer to self, already in r3 + mr r4,r12 // 1, stub number + addi r5, r1, 204 // 2, pointer to the parameter area in our + // caller's stack, for access to + // parameters beyond those passed in + // registers. Skip past the first parameter + // (corresponding to r3) for the same reason + // as above. 176 (size of our frame) + 24 + // (size of caller's linkage) + 4 (skipped + // parameter) + addi r6, r1, 44 // 3, pointer to saved GPRs + addi r7, r1, 72 // 4, pointer to saved FPRs + + bl L_PrepareAndDispatch$stub + // Do it + nop // Leave room for linker magic + + // Epilog(ue) + lwz r0, 184(r1) // Retrieve old link register value + addi r1, r1, 176 // Restore stack pointer + mtlr r0 // Restore link register + blr // Return + +.picsymbol_stub +L_PrepareAndDispatch$stub: // Standard PIC symbol stub + .indirect_symbol _PrepareAndDispatch + mflr r0 + bcl 20,31,L1$pb +L1$pb: + mflr r11 + addis r11,r11,ha16(L1$lz-L1$pb) + mtlr r0 + lwz r12,lo16(L1$lz-L1$pb)(r11) + mtctr r12 + addi r11,r11,lo16(L1$lz-L1$pb) + bctr +.lazy_symbol_pointer +L1$lz: + .indirect_symbol _PrepareAndDispatch + .long dyld_stub_binding_helper diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S new file mode 100644 index 000000000..72a5a9f4b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S @@ -0,0 +1,77 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl SharedStub + .type SharedStub,@function + +SharedStub: + stwu sp,-112(sp) // room for + // linkage (8), + // gprData (32), + // fprData (64), + // stack alignment(8) + mflr r0 + stw r0,116(sp) // save LR backchain + + stw r4,12(sp) // save GP registers + stw r5,16(sp) // (n.b. that we don't save r3 + stw r6,20(sp) // because PrepareAndDispatch() is savvy) + stw r7,24(sp) + stw r8,28(sp) + stw r9,32(sp) + stw r10,36(sp) +#ifndef __NO_FPRS__ + stfd f1,40(sp) // save FP registers + stfd f2,48(sp) + stfd f3,56(sp) + stfd f4,64(sp) + stfd f5,72(sp) + stfd f6,80(sp) + stfd f7,88(sp) + stfd f8,96(sp) +#endif + + // r3 has the 'self' pointer already + + mr r4,r11 // r4 <= methodIndex selector, passed + // via r11 in the nsXPTCStubBase::StubXX() call + + addi r5,sp,120 // r5 <= pointer to callers args area, + // beyond r3-r10/f1-f8 mapped range + + addi r6,sp,8 // r6 <= gprData +#ifndef __NO_FPRS__ + addi r7,sp,40 // r7 <= fprData +#else + li r7, 0 // r7 should be unused +#endif + + bl PrepareAndDispatch@local // Go! + + lwz r0,116(sp) // restore LR + mtlr r0 + la sp,112(sp) // clean up the stack + blr + +/* Magic indicating no need for an executable stack */ +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s new file mode 100644 index 000000000..8d43165ba --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s @@ -0,0 +1,70 @@ +# -*- Mode: Asm -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl SharedStub + .type SharedStub,@function + +SharedStub: + stwu sp,-112(sp) # room for + # linkage (8), + # gprData (32), + # fprData (64), + # stack alignment(8) + mflr r0 + stw r0,116(sp) # save LR backchain + + stw r4,12(sp) # save GP registers + stw r5,16(sp) # (n.b. that we don't save r3 + stw r6,20(sp) # because PrepareAndDispatch() is savvy) + stw r7,24(sp) + stw r8,28(sp) + stw r9,32(sp) + stw r10,36(sp) + + stfd f1,40(sp) # save FP registers + stfd f2,48(sp) + stfd f3,56(sp) + stfd f4,64(sp) + stfd f5,72(sp) + stfd f6,80(sp) + stfd f7,88(sp) + stfd f8,96(sp) + + # r3 has the 'self' pointer already + + mr r4,r11 # r4 <= methodIndex selector, passed + # via r11 in the nsXPTCStubBase::StubXX() call + + addi r5,sp,120 # r5 <= pointer to callers args area, + # beyond r3-r10/f1-f8 mapped range + + addi r6,sp,8 # r6 <= gprData + addi r7,sp,40 # r7 <= fprData + + bl PrepareAndDispatch@local # Go! + + lwz r0,116(sp) # restore LR + mtlr r0 + la sp,112(sp) # clean up the stack + blr + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S new file mode 100644 index 000000000..dcca08205 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S @@ -0,0 +1,72 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl SharedStub + .type SharedStub,@function + +SharedStub: + stwu sp,-112(sp) // room for + // linkage (8), + // gprData (32), + // fprData (64), + // stack alignment(8) + mflr r0 + stw r0,116(sp) // save LR backchain + + stw r4,12(sp) // save GP registers + stw r5,16(sp) // (n.b. that we don't save r3 + stw r6,20(sp) // because PrepareAndDispatch() is savvy) + stw r7,24(sp) + stw r8,28(sp) + stw r9,32(sp) + stw r10,36(sp) + + stfd f1,40(sp) // save FP registers + stfd f2,48(sp) + stfd f3,56(sp) + stfd f4,64(sp) + stfd f5,72(sp) + stfd f6,80(sp) + stfd f7,88(sp) + stfd f8,96(sp) + + // r3 has the 'self' pointer already + + mr r4,r11 // r4 <= methodIndex selector, passed + // via r11 in the nsXPTCStubBase::StubXX() call + + addi r5,sp,120 // r5 <= pointer to callers args area, + // beyond r3-r10/f1-f8 mapped range + + addi r6,sp,8 // r6 <= gprData + addi r7,sp,40 // r7 <= fprData + + bl PrepareAndDispatch@local // Go! + + lwz r0,116(sp) // restore LR + mtlr r0 + la sp,112(sp) // clean up the stack + blr + +// Magic indicating no need for an executable stack +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s new file mode 100644 index 000000000..ab97a890c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s @@ -0,0 +1,50 @@ +/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') + +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + stx %i1, [%fp + 0x7ff + 136] + stx %i2, [%fp + 0x7ff + 144] + stx %i3, [%fp + 0x7ff + 152] + stx %i4, [%fp + 0x7ff + 160] + stx %i5, [%fp + 0x7ff + 168] +! now we can build our own stack frame + save %sp,-(128 + 64),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 64 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s new file mode 100644 index 000000000..9b448d7c7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + st %i1, [%fp + 72] + st %i2, [%fp + 76] + st %i3, [%fp + 80] + st %i4, [%fp + 84] + st %i5, [%fp + 88] +! now we can build our own stack frame + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s new file mode 100644 index 000000000..871556d4c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + st %i1, [%fp + 72] + st %i2, [%fp + 76] + st %i3, [%fp + 80] + st %i4, [%fp + 84] + st %i5, [%fp + 88] +! now we can build our own stack frame + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s new file mode 100644 index 000000000..9b448d7c7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + st %i1, [%fp + 72] + st %i2, [%fp + 76] + st %i3, [%fp + 80] + st %i4, [%fp + 84] + st %i5, [%fp + 88] +! now we can build our own stack frame + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s new file mode 100644 index 000000000..ab97a890c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s @@ -0,0 +1,50 @@ +/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') + +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + stx %i1, [%fp + 0x7ff + 136] + stx %i2, [%fp + 0x7ff + 144] + stx %i3, [%fp + 0x7ff + 152] + stx %i4, [%fp + 0x7ff + 160] + stx %i5, [%fp + 0x7ff + 168] +! now we can build our own stack frame + save %sp,-(128 + 64),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 64 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s new file mode 100644 index 000000000..aa6d84434 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s @@ -0,0 +1,63 @@ +#define STUB_ENTRY1(nn) \ + .globl __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \ + .hidden __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \ + .type __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, @function; \ +__1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_: \ + movl $/**/nn/**/, %eax; \ + jmp SharedStub; \ + .size __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_ \ + +#define STUB_ENTRY2(nn) \ + .globl __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \ + .hidden __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \ + .type __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, @function; \ +__1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_: \ + movl $/**/nn/**/, %eax; \ + jmp SharedStub; \ + .size __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_ \ + +#define STUB_ENTRY3(nn) \ + .globl __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \ + .hidden __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \ + .type __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, @function; \ +__1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_: \ + movl $/**/nn/**/, %eax; \ + jmp SharedStub; \ + .size __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_ \ + +// static nsresult SharedStub(uint32_t methodIndex) + .type SharedStub, @function; + SharedStub: + // make room for gpregs (48), fpregs (64) + pushq %rbp; + movq %rsp,%rbp; + subq $112,%rsp; + // save GP registers + movq %rdi,-112(%rbp); + movq %rsi,-104(%rbp); + movq %rdx, -96(%rbp); + movq %rcx, -88(%rbp); + movq %r8 , -80(%rbp); + movq %r9 , -72(%rbp); + leaq -112(%rbp),%rcx; + // save FP registers + movsd %xmm0,-64(%rbp); + movsd %xmm1,-56(%rbp); + movsd %xmm2,-48(%rbp); + movsd %xmm3,-40(%rbp); + movsd %xmm4,-32(%rbp); + movsd %xmm5,-24(%rbp); + movsd %xmm6,-16(%rbp); + movsd %xmm7, -8(%rbp); + leaq -64(%rbp),%r8; + // rdi has the 'self' pointer already + movl %eax,%esi; + leaq 16(%rbp),%rdx; + call PrepareAndDispatch@plt; + leave; + ret; + .size SharedStub, . - SharedStub + +#define SENTINEL_ENTRY(nn) + +#include "xptcstubsdef_asm.solx86" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s new file mode 100644 index 000000000..76bdcf925 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s @@ -0,0 +1,78 @@ +#define STUB_ENTRY1(nn) \ + .globl __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \ + .type __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, @function; \ +__1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_: \ + push %ebp; \ + movl %esp,%ebp; \ + andl $-16,%esp; \ + push %ebx; \ + call .CG4./**/nn/**/; \ +.CG4./**/nn/**/: \ + pop %ebx; \ + addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \ + leal 0xc(%ebp), %ecx; \ + pushl %ecx; \ + pushl $/**/nn/**/; \ + movl 0x8(%ebp), %ecx; \ + pushl %ecx; \ + call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \ + addl $0xc , %esp; \ + pop %ebx; \ + movl %ebp,%esp; \ + pop %ebp; \ + ret ; \ + .size __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_ \ + +#define STUB_ENTRY2(nn) \ + .globl __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \ + .type __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, @function; \ +__1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_: \ + push %ebp; \ + movl %esp,%ebp; \ + andl $-16,%esp; \ + push %ebx; \ + call .CG4./**/nn/**/; \ +.CG4./**/nn/**/: \ + pop %ebx; \ + addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \ + leal 0xc(%ebp), %ecx; \ + pushl %ecx; \ + pushl $/**/nn/**/; \ + movl 0x8(%ebp), %ecx; \ + pushl %ecx; \ + call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \ + addl $0xc , %esp; \ + pop %ebx; \ + movl %ebp,%esp; \ + pop %ebp; \ + ret ; \ + .size __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_ \ + +#define STUB_ENTRY3(nn) \ + .globl __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \ + .type __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, @function; \ +__1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_: \ + push %ebp; \ + movl %esp,%ebp; \ + andl $-16,%esp; \ + push %ebx; \ + call .CG4./**/nn/**/; \ +.CG4./**/nn/**/: \ + pop %ebx; \ + addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \ + leal 0xc(%ebp), %ecx; \ + pushl %ecx; \ + pushl $/**/nn/**/; \ + movl 0x8(%ebp), %ecx; \ + pushl %ecx; \ + call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \ + addl $0xc , %esp; \ + pop %ebx; \ + movl %ebp,%esp; \ + pop %ebp; \ + ret ; \ + .size __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_ \ + +#define SENTINEL_ENTRY(nn) + +#include "xptcstubsdef_asm.solx86" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp new file mode 100644 index 000000000..49edfca44 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp @@ -0,0 +1,16 @@ +/* -*- Mode: C -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#if defined(__i386__) +#include "xptcstubs_gcc_x86_unix.cpp" +#elif defined(__x86_64__) +#include "xptcstubs_x86_64_darwin.cpp" +#elif defined(__ppc__) +#include "xptcstubs_ppc_rhapsody.cpp" +#elif defined(__arm__) +#include "xptcstubs_arm.cpp" +#else +#error unknown cpu architecture +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp new file mode 100644 index 000000000..6811a26ad --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp @@ -0,0 +1,139 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" +#include "xptc_gcc_x86_unix.h" + +extern "C" { +static nsresult ATTRIBUTE_USED +__attribute__ ((regparm (3))) +PrepareAndDispatch(uint32_t methodIndex, nsXPTCStubBase* self, uint32_t* args) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + dp->val.p = (void*) *ap; + switch(type) + { + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} +} // extern "C" + +#if !defined(XP_MACOSX) + +#define STUB_HEADER(a, b) ".hidden " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t" \ + ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,@function\n" + +#define STUB_SIZE(a, b) ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t" + +#else + +#define STUB_HEADER(a, b) +#define STUB_SIZE(a, b) + +#endif + +// gcc3 mangling tends to insert the length of the method name +#define STUB_ENTRY(n) \ +asm(".text\n\t" \ + ".align 2\n\t" \ + ".if " #n " < 10\n\t" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + STUB_HEADER(5, n) \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + STUB_HEADER(6, n) \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 1000\n\t" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + STUB_HEADER(7, n) \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \ + ".else\n\t" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ + ".endif\n\t" \ + "movl $" #n ", %eax\n\t" \ + "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \ + ".if " #n " < 10\n\t" \ + STUB_SIZE(5, n) \ + ".elseif " #n " < 100\n\t" \ + STUB_SIZE(6, n) \ + ".else\n\t" \ + STUB_SIZE(7, n) \ + ".endif"); + +// static nsresult SharedStub(uint32_t methodIndex) __attribute__((regparm(1))) +asm(".text\n\t" + ".align 2\n\t" +#if !defined(XP_MACOSX) + ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t" +#endif + SYMBOL_UNDERSCORE "SharedStub:\n\t" + "leal 0x08(%esp), %ecx\n\t" + "movl 0x04(%esp), %edx\n\t" + "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t" +#if !defined(XP_MACOSX) + ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub" +#endif +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +void +xptc_dummy() +{ +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp new file mode 100644 index 000000000..e2d37e4f5 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp @@ -0,0 +1,151 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#include <stddef.h> +#include <stdlib.h> + +// "This code is for IA64 only" + +/* Implement shared vtbl methods. */ + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs) +{ + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + nsresult result = NS_ERROR_FAILURE; + uint64_t* iargs = intargs; + uint64_t* fargs = floatargs; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + if (! dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + for(i = 0; i < paramCount; ++i) + { + int isfloat = 0; + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + dp->val.p = (void*) *iargs; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) iargs; + dp->val.p = (void*) (*(adr+1)); +#endif + } + else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break; + case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break; + case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break; + case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break; + case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break; + case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break; + case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break; + case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break; + case nsXPTType::T_FLOAT : + isfloat = 1; + if (i < 7) + dp->val.f = (float) *((double*) fargs); /* register */ + else + dp->val.u32 = *(fargs); /* memory */ + break; + case nsXPTType::T_DOUBLE : + isfloat = 1; + dp->val.u64 = *(fargs); + break; + case nsXPTType::T_BOOL : dp->val.b = *(iargs); break; + case nsXPTType::T_CHAR : dp->val.c = *(iargs); break; + case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break; + default: + NS_ERROR("bad type"); + break; + } + if (i < 7) + { + /* we are parsing register arguments */ + if (i == 6) + { + // run out of register arguments, move on to memory arguments + iargs = restargs; + fargs = restargs; + } + else + { + ++iargs; // advance one integer register slot + if (isfloat) ++fargs; // advance float register slot if isfloat + } + } + else + { + /* we are parsing memory arguments */ + ++iargs; + ++fargs; + } + } + + result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *); + +/* Variable a0-a7 were put there so we can have access to the 8 input + registers on Stubxyz entry */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \ +uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \ +uint64_t a8) \ +{ uint64_t a0 = (uint64_t) this; \ + return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp new file mode 100644 index 000000000..fea9e8e3d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp @@ -0,0 +1,154 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> + +// "This code is for IA64 only" + +/* Implement shared vtbl methods. */ + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs) +{ + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + nsresult result = NS_ERROR_FAILURE; + uint64_t* iargs = intargs; + uint64_t* fargs = floatargs; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + if (! dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + for(i = 0; i < paramCount; ++i) + { + int isfloat = 0; + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + dp->val.p = (void*) *iargs; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) iargs; + dp->val.p = (void*) (*(adr+1)); +#endif + } + else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break; + case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break; + case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break; + case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break; + case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break; + case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break; + case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break; + case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break; + case nsXPTType::T_FLOAT : + isfloat = 1; + if (i < 7) + dp->val.f = (float) *((double*) fargs); /* register */ + else + dp->val.u32 = *(fargs); /* memory */ + break; + case nsXPTType::T_DOUBLE : + isfloat = 1; + dp->val.u64 = *(fargs); + break; + case nsXPTType::T_BOOL : dp->val.b = *(iargs); break; + case nsXPTType::T_CHAR : dp->val.c = *(iargs); break; + case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break; + default: + NS_ERROR("bad type"); + break; + } + if (i < 7) + { + /* we are parsing register arguments */ + if (i == 6) + { + // run out of register arguments, move on to memory arguments + iargs = restargs; + fargs = restargs; + } + else + { + ++iargs; // advance one integer register slot + if (isfloat) ++fargs; // advance float register slot if isfloat + } + } + else + { + /* we are parsing memory arguments */ + ++iargs; + ++fargs; + } + } + + result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *); + +/* Variable a0-a7 were put there so we can have access to the 8 input + registers on Stubxyz entry */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \ +uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \ +uint64_t a8) \ +{ uint64_t a0 = (uint64_t) this; \ + return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp new file mode 100644 index 000000000..d9c41aee7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp @@ -0,0 +1,187 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +__asm__("PrepareAndDispatch") ATTRIBUTE_USED; + +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +{ + const uint8_t PARAM_BUFFER_COUNT = 16; + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + // args[0] to args[NUM_ARG_REGS] hold floating point register values + uint64_t* ap = args + NUM_ARG_REGS; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break; + case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break; + case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break; + case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break; + case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break; + case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break; + case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break; + case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // floats passed via registers are stored as doubles + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (uint64_t) args[i]; + dp->val.f = (float) dp->val.d; // convert double to float + } + else + dp->val.u32 = (uint32_t) *ap; + break; + case nsXPTType::T_DOUBLE : + // doubles passed via registers are also stored + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap; + break; + case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break; + case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break; + case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +/* + * SharedStub() + * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is + * passed to this function via $1 to preserve the argument registers. + */ +__asm__( + "#### SharedStub ####\n" +".text\n\t" + ".align 5\n\t" + ".ent SharedStub\n" +"SharedStub:\n\t" + ".frame $30,96,$26,0\n\t" + ".mask 0x4000000,-96\n\t" + "ldgp $29,0($27)\n" +"$SharedStub..ng:\n\t" + "subq $30,96,$30\n\t" + "stq $26,0($30)\n\t" + ".prologue 1\n\t" + + /* + * Store arguments passed via registers to the stack. + * Floating point registers are stored as doubles and converted + * to floats in PrepareAndDispatch if necessary. + */ + "stt $f17,16($30)\n\t" /* floating point registers */ + "stt $f18,24($30)\n\t" + "stt $f19,32($30)\n\t" + "stt $f20,40($30)\n\t" + "stt $f21,48($30)\n\t" + "stq $17,56($30)\n\t" /* integer registers */ + "stq $18,64($30)\n\t" + "stq $19,72($30)\n\t" + "stq $20,80($30)\n\t" + "stq $21,88($30)\n\t" + + /* + * Call PrepareAndDispatch function. + */ + "bis $1,$1,$17\n\t" /* pass "methodIndex" */ + "addq $30,16,$18\n\t" /* pass "args" */ + "bsr $26,$PrepareAndDispatch..ng\n\t" + + "ldq $26,0($30)\n\t" + "addq $30,96,$30\n\t" + "ret $31,($26),1\n\t" + ".end SharedStub" + ); + +/* + * nsresult nsXPTCStubBase::Stub##n() + * Sets register $1 to "methodIndex" and jumps to SharedStub. + */ +#define STUB_MANGLED_ENTRY(n, symbol) \ + "#### Stub"#n" ####" "\n\t" \ + ".text" "\n\t" \ + ".align 5" "\n\t" \ + ".globl " symbol "\n\t" \ + ".ent " symbol "\n" \ +symbol ":" "\n\t" \ + ".frame $30,0,$26,0" "\n\t" \ + "ldgp $29,0($27)" "\n" \ +"$" symbol "..ng:" "\n\t" \ + ".prologue 1" "\n\t" \ + "lda $1,"#n "\n\t" \ + "br $31,$SharedStub..ng" "\n\t" \ + ".end " symbol + +#define STUB_ENTRY(n) \ +__asm__( \ + ".if "#n" < 10" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 100" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 1000" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \ + ".else" "\n\t" \ + ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \ + ".endif" \ + ); + + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp new file mode 100644 index 000000000..3720a5c37 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +extern "C" { + nsresult ATTRIBUTE_USED + PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) + { +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + + switch(type) + { + // the 8 and 16 bit types will have been promoted to 32 bits before + // being pushed onto the stack. Since the 68k is big endian, we + // need to skip over the leading high order bytes. + case nsXPTType::T_I8 : dp->val.i8 = *(((int8_t*) ap) + 3); break; + case nsXPTType::T_I16 : dp->val.i16 = *(((int16_t*) ap) + 1); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *(((uint8_t*) ap) + 3); break; + case nsXPTType::T_U16 : dp->val.u16 = *(((uint16_t*)ap) + 1); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t* ap); break; + case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; + } +} + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + void *frame = __builtin_frame_address(0); \ + return PrepareAndDispatch(this, n, (uint32_t*)frame + 3); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp new file mode 100644 index 000000000..cf4ab1268 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +static nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint32_t* a_gpr, uint64_t *a_fpr, uint32_t *a_ov) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t gpr = 1, fpr = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (gpr < 5) + dp->val.p = (void*) *a_gpr++, gpr++; + else + dp->val.p = (void*) *a_ov++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + dp->val.i8 = *((int32_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i8 = *((int32_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + dp->val.i16 = *((int32_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i16 = *((int32_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + dp->val.i32 = *((int32_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i32 = *((int32_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 4) + dp->val.i64 = *((int64_t*) a_gpr), a_gpr+=2, gpr+=2; + else + dp->val.i64 = *((int64_t*) a_ov ), a_ov+=2, gpr=5; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + dp->val.u8 = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u8 = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + dp->val.u16 = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u16 = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + dp->val.u32 = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u32 = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 4) + dp->val.u64 = *((uint64_t*)a_gpr), a_gpr+=2, gpr+=2; + else + dp->val.u64 = *((uint64_t*)a_ov ), a_ov+=2, gpr=5; + break; + case nsXPTType::T_FLOAT : + if (fpr < 2) + dp->val.f = *((float*) a_fpr), a_fpr++, fpr++; + else + dp->val.f = *((float*) a_ov ), a_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 2) + dp->val.d = *((double*) a_fpr), a_fpr++, fpr++; + else + dp->val.d = *((double*) a_ov ), a_ov+=2; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + dp->val.b = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.b = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + dp->val.c = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.c = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + dp->val.wc = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.wc = *((uint32_t*)a_ov ), a_ov++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + uint32_t a_gpr[4]; \ + uint64_t a_fpr[2]; \ + uint32_t *a_ov; \ + \ + __asm__ __volatile__ \ + ( \ + "l %0,0(15)\n\t" \ + "ahi %0,96\n\t" \ + "stm 3,6,0(%3)\n\t" \ + "std 0,%1\n\t" \ + "std 2,%2\n\t" \ + : "=&a" (a_ov), \ + "=m" (a_fpr[0]), \ + "=m" (a_fpr[1]) \ + : "a" (a_gpr) \ + : "memory", "cc", \ + "3", "4", "5", "6" \ + ); \ + \ + return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp new file mode 100644 index 000000000..189cceb82 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp @@ -0,0 +1,187 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +static nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint64_t* a_gpr, uint64_t *a_fpr, uint64_t *a_ov) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t gpr = 1, fpr = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (gpr < 5) + dp->val.p = (void*) *a_gpr++, gpr++; + else + dp->val.p = (void*) *a_ov++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + dp->val.i8 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i8 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + dp->val.i16 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i16 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + dp->val.i32 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i32 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 5) + dp->val.i64 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i64 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + dp->val.u8 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u8 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + dp->val.u16 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u16 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + dp->val.u32 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u32 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 5) + dp->val.u64 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u64 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_FLOAT : + if (fpr < 4) + dp->val.f = *((float*) a_fpr), a_fpr++, fpr++; + else + dp->val.f = *(((float*) a_ov )+1), a_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 4) + dp->val.d = *((double*) a_fpr), a_fpr++, fpr++; + else + dp->val.d = *((double*) a_ov ), a_ov++; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + dp->val.b = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.b = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + dp->val.c = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.c = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + dp->val.wc = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.wc = *((uint64_t*)a_ov ), a_ov++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + uint64_t a_gpr[4]; \ + uint64_t a_fpr[4]; \ + uint64_t *a_ov; \ + \ + __asm__ __volatile__ \ + ( \ + "lg %0,0(15)\n\t" \ + "aghi %0,160\n\t" \ + "stmg 3,6,0(%5)\n\t"\ + "std 0,%1\n\t" \ + "std 2,%2\n\t" \ + "std 4,%3\n\t" \ + "std 6,%4\n\t" \ + : "=&a" (a_ov), \ + "=m" (a_fpr[0]), \ + "=m" (a_fpr[1]), \ + "=m" (a_fpr[2]), \ + "=m" (a_fpr[3]) \ + : "a" (a_gpr) \ + : "memory", "cc", \ + "3", "4", "5", "6" \ + ); \ + \ + return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp new file mode 100644 index 000000000..75f8562ce --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp @@ -0,0 +1,112 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#include <stdint.h> + +/* + * This is for MIPS O32 ABI + * Args contains a0-3 and then the stack. + * Because a0 is 'this', we want to skip it + */ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + args++; // always skip over a0 + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + + switch(type) + { + case nsXPTType::T_I64 : + if ((intptr_t)ap & 4) ap++; + dp->val.i64 = *((int64_t*) ap); ap++; + break; + case nsXPTType::T_U64 : + if ((intptr_t)ap & 4) ap++; + dp->val.u64 = *((int64_t*) ap); ap++; + break; + case nsXPTType::T_DOUBLE: + if ((intptr_t)ap & 4) ap++; + dp->val.d = *((double*) ap); ap++; + break; +#ifdef IS_LITTLE_ENDIAN + default: + dp->val.p = (void*) *ap; + break; +#else + case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break; + case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break; + case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break; + case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break; + case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break; + case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break; + case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break; + case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break; + case nsXPTType::T_WCHAR : dp->val.wc = (wchar_t) *ap; break; + case nsXPTType::T_FLOAT : dp->val.f = *(float *) ap; break; + default: + NS_ASSERTION(0, "bad type"); + break; +#endif + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) // done in the .s file + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp new file mode 100644 index 000000000..a4b553940 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp @@ -0,0 +1,185 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64) +#error "This code is for MIPS n32/n64 only" +#endif + +/* + * This is for MIPS n32/n64 ABI + * + * When we're called, the "gp" registers are stored in gprData and + * the "fp" registers are stored in fprData. There are 8 regs + * available which correspond to the first 7 parameters of the + * function and the "this" pointer. If there are additional parms, + * they are stored on the stack at address "args". + * + */ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, + uint64_t *gprData, double *fprData) +{ +#define PARAM_BUFFER_COUNT 16 +#define PARAM_GPR_COUNT 7 +#define PARAM_FPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint64_t* ap = args; + uint32_t iCount = 0; + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*)gprData[iCount++]; + else + dp->val.p = (void*)*ap++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8: + if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t)gprData[iCount++]; + else + dp->val.i8 = (int8_t)*ap++; + break; + + case nsXPTType::T_I16: + if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t)gprData[iCount++]; + else + dp->val.i16 = (int16_t)*ap++; + break; + + case nsXPTType::T_I32: + if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t)gprData[iCount++]; + else + dp->val.i32 = (int32_t)*ap++; + break; + + case nsXPTType::T_I64: + if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t)gprData[iCount++]; + else + dp->val.i64 = (int64_t)*ap++; + break; + + case nsXPTType::T_U8: + if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t)gprData[iCount++]; + else + dp->val.u8 = (uint8_t)*ap++; + break; + + case nsXPTType::T_U16: + if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t)gprData[iCount++]; + else + dp->val.u16 = (uint16_t)*ap++; + break; + + case nsXPTType::T_U32: + if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t)gprData[iCount++]; + else + dp->val.u32 = (uint32_t)*ap++; + break; + + case nsXPTType::T_U64: + if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t)gprData[iCount++]; + else + dp->val.u64 = (uint64_t)*ap++; + break; + + case nsXPTType::T_FLOAT: + if (iCount < PARAM_FPR_COUNT) + dp->val.f = (double)fprData[iCount++]; + else + dp->val.f = *((double*)ap++); + break; + + case nsXPTType::T_DOUBLE: + if (iCount < PARAM_FPR_COUNT) + dp->val.d = (double)fprData[iCount++]; + else + dp->val.d = *((double*)ap++); + break; + + case nsXPTType::T_BOOL: + if (iCount < PARAM_GPR_COUNT) + dp->val.b = (bool)gprData[iCount++]; + else + dp->val.b = (bool)*ap++; + break; + + case nsXPTType::T_CHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char)gprData[iCount++]; + else + dp->val.c = (char)*ap++; + break; + + case nsXPTType::T_WCHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t)gprData[iCount++]; + else + dp->val.wc = (wchar_t)*ap++; + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) /* defined in the assembly file */ + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp new file mode 100644 index 000000000..680114fd5 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp @@ -0,0 +1,115 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if !defined(__NetBSD__) || !defined(__m68k__) +#error This code is for NetBSD/m68k only +#endif + +extern "C" { + static nsresult ATTRIBUTE_USED + PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) + { +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + nsIInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + + switch(type) + { + // the 8 and 16 bit types will have been promoted to 32 bits before + // being pushed onto the stack. Since the 68k is big endian, we + // need to skip over the leading high order bytes. + case nsXPTType::T_I8 : dp->val.i8 = *(((int8_t*) ap) + 3); break; + case nsXPTType::T_I16 : dp->val.i16 = *(((int16_t*) ap) + 1); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *(((uint8_t*) ap) + 3); break; + case nsXPTType::T_U16 : dp->val.u16 = *(((uint16_t*)ap) + 1); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *(((char*) ap) + 3); break; + case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break; + // wchar_t is an int (32 bits) on NetBSD + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + NS_RELEASE(iface_info); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; + } +} + +#define STUB_ENTRY(n) \ +__asm__( \ + ".global _Stub"#n"__14nsXPTCStubBase\n\t" \ +"_Stub"#n"__14nsXPTCStubBase:\n\t" \ + "link a6,#0 \n\t" \ + "lea a6@(12), a0 \n\t" /* pointer to args */ \ + "movl a0, sp@- \n\t" \ + "movl #"#n", sp@- \n\t" /* method index */ \ + "movl a6@(8), sp@- \n\t" /* this */ \ + "jbsr _PrepareAndDispatch \n\t" \ + "unlk a6 \n\t" \ + "rts \n\t" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp new file mode 100644 index 000000000..7353709f1 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp @@ -0,0 +1,143 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if _HPUX +#error "This code is for HP-PA RISC 32 bit mode only" +#endif + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint32_t* args, uint32_t* floatargs) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + int32_t regwords = 1; /* self pointer is not in the variant records */ + nsresult result = NS_ERROR_FAILURE; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + for(i = 0; i < paramCount; ++i, --args) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *args; + ++regwords; + continue; + } + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) args); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) args); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) args); break; + case nsXPTType::T_DOUBLE : + if (regwords & 1) + { + ++regwords; /* align on double word */ + --args; + } + if (regwords == 0 || regwords == 2) + { + dp->val.d=*((double*) (floatargs + regwords)); + --args; + } + else + { + dp->val.d = *((double*) --args); + } + regwords += 2; + continue; + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : + if (regwords & 1) + { + ++regwords; /* align on double word */ + --args; + } + ((DU *)dp)->lo = *((uint32_t*) args); + ((DU *)dp)->hi = *((uint32_t*) --args); + regwords += 2; + continue; + case nsXPTType::T_FLOAT : + if (regwords >= 4) + dp->val.f = *((float*) args); + else + dp->val.f = *((float*) floatargs+4+regwords); + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*) args); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*) args); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*) args); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*) args); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*) args); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) args); break; + default: + NS_ERROR("bad type"); + break; + } + ++regwords; + } + + result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(int); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + return SharedStub(n); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp new file mode 100644 index 000000000..95e67cb29 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +#include "xptcprivate.h" +#include "xptiprivate.h" + +// The Linux/PPC64 ABI passes the first 8 integral +// parameters and the first 13 floating point parameters in registers +// (r3-r10 and f1-f13), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the caller's stack +// area. The stack pointer has to retain 16-byte alignment. + +// The PowerPC64 platform ABI can be found here: +// http://www.freestandards.org/spec/ELF/ppc64/ +// and in particular: +// http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL + +#define PARAM_BUFFER_COUNT 16 +#define GPR_COUNT 7 +#define FPR_COUNT 13 + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gprData[]' contains the arguments passed in integer registers +// - 'fprData[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. +#include <stdio.h> +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, + uint64_t methodIndex, + uint64_t* args, + uint64_t *gprData, + double *fprData) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (! dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint64_t* ap = args; + uint64_t tempu64; + + for(i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (i < FPR_COUNT) + dp->val.d = fprData[i]; + else + dp->val.d = *(double*) ap; + } else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (i < FPR_COUNT) + dp->val.f = (float) fprData[i]; // in registers floats are passed as doubles + else { + float *p = (float *)ap; +#ifndef __LITTLE_ENDIAN__ + p++; +#endif + dp->val.f = *p; + } + } else { /* integer type or pointer */ + if (i < GPR_COUNT) + tempu64 = gprData[i]; + else + tempu64 = *ap; + + if (param.IsOut() || !type.IsArithmetic()) + dp->val.p = (void*) tempu64; + else if (type == nsXPTType::T_I8) + dp->val.i8 = (int8_t) tempu64; + else if (type == nsXPTType::T_I16) + dp->val.i16 = (int16_t) tempu64; + else if (type == nsXPTType::T_I32) + dp->val.i32 = (int32_t) tempu64; + else if (type == nsXPTType::T_I64) + dp->val.i64 = (int64_t) tempu64; + else if (type == nsXPTType::T_U8) + dp->val.u8 = (uint8_t) tempu64; + else if (type == nsXPTType::T_U16) + dp->val.u16 = (uint16_t) tempu64; + else if (type == nsXPTType::T_U32) + dp->val.u32 = (uint32_t) tempu64; + else if (type == nsXPTType::T_U64) + dp->val.u64 = (uint64_t) tempu64; + else if (type == nsXPTType::T_BOOL) + dp->val.b = (bool) tempu64; + else if (type == nsXPTType::T_CHAR) + dp->val.c = (char) tempu64; + else if (type == nsXPTType::T_WCHAR) + dp->val.wc = (wchar_t) tempu64; + else + NS_ERROR("bad type"); + } + + if (i >= 7) + ap++; + } + + result = self->mOuter->CallMethod((uint16_t) methodIndex, info, + dispatchParams); + + if (dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +// Load r11 with the constant 'n' and branch to SharedStub(). +// +// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; +// however, it's quick, dirty, and'll break when the ABI changes on +// us, which is what we want ;-). + + +// gcc-3 version +// +// As G++3 ABI contains the length of the functionname in the mangled +// name, it is difficult to get a generic assembler mechanism like +// in the G++ 2.95 case. +// Create names would be like: +// _ZN14nsXPTCStubBase5Stub1Ev +// _ZN14nsXPTCStubBase6Stub12Ev +// _ZN14nsXPTCStubBase7Stub123Ev +// _ZN14nsXPTCStubBase8Stub1234Ev +// etc. +// Use assembler directives to get the names right... + +#if _CALL_ELF == 2 +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".section \".text\" \n\t" \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + "0: addis 2,12,.TOC.-0b@ha \n\t" \ + "addi 2,2,.TOC.-0b@l \n\t" \ + ".localentry _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + "0: addis 2,12,.TOC.-0b@ha \n\t" \ + "addi 2,2,.TOC.-0b@l \n\t" \ + ".localentry _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + "0: addis 2,12,.TOC.-0b@ha \n\t" \ + "addi 2,2,.TOC.-0b@l \n\t" \ + ".localentry _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub \n" \ +); +#else +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".section \".toc\",\"aw\" \n\t" \ + ".section \".text\" \n\t" \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".section \".opd\",\"aw\" \n\t" \ + ".align 3 \n\t" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + ".quad ._ZN14nsXPTCStubBase5Stub"#n"Ev,.TOC.@tocbase \n\t" \ + ".previous \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"._ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".section \".opd\",\"aw\" \n\t" \ + ".align 3 \n\t" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + ".quad ._ZN14nsXPTCStubBase6Stub"#n"Ev,.TOC.@tocbase \n\t" \ + ".previous \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"._ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".section \".opd\",\"aw\" \n\t" \ + ".align 3 \n\t" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + ".quad ._ZN14nsXPTCStubBase7Stub"#n"Ev,.TOC.@tocbase \n\t" \ + ".previous \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"._ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub \n" \ +); +#endif + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp new file mode 100644 index 000000000..0463c21c5 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp @@ -0,0 +1,185 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if defined(AIX) + +/* + For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters + arrive in a separate chunk of data that has been loaded from the registers. + The args pointer has been set to the start of the parameters BEYOND the ones + arriving in registers +*/ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args, uint32_t *gprData, double *fprData) +{ + typedef struct { + uint32_t hi; + uint32_t lo; // have to move 64 bit entities as 32 bit halves since + } DU; // stack slots are not guaranteed 16 byte aligned + +#define PARAM_BUFFER_COUNT 16 +#define PARAM_GPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + uint32_t iCount = 0; + uint32_t fpCount = 0; + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*) gprData[iCount++]; + else + dp->val.p = (void*) *ap++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t) gprData[iCount++]; + else + dp->val.i8 = (int8_t) *ap++; + break; + case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t) gprData[iCount++]; + else + dp->val.i16 = (int16_t) *ap++; + break; + case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t) gprData[iCount++]; + else + dp->val.i32 = (int32_t) *ap++; + break; + case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->hi = (int32_t) gprData[iCount++]; + else + ((DU *)dp)->hi = (int32_t) *ap++; + if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->lo = (uint32_t) gprData[iCount++]; + else + ((DU *)dp)->lo = (uint32_t) *ap++; + break; + case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t) gprData[iCount++]; + else + dp->val.u8 = (uint8_t) *ap++; + break; + case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t) gprData[iCount++]; + else + dp->val.u16 = (uint16_t) *ap++; + break; + case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t) gprData[iCount++]; + else + dp->val.u32 = (uint32_t) *ap++; + break; + case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->hi = (uint32_t) gprData[iCount++]; + else + ((DU *)dp)->hi = (uint32_t) *ap++; + if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->lo = (uint32_t) gprData[iCount++]; + else + ((DU *)dp)->lo = (uint32_t) *ap++; + break; + case nsXPTType::T_FLOAT : if (fpCount < 13) { + dp->val.f = (float) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else + dp->val.f = *((float*) ap++); + break; + case nsXPTType::T_DOUBLE : if (fpCount < 13) { + dp->val.d = (double) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else { + dp->val.f = *((double*) ap); + ap += 2; + } + break; + case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT) + dp->val.b = (bool) gprData[iCount++]; + else + dp->val.b = (bool) *ap++; + break; + case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char) gprData[iCount++]; + else + dp->val.c = (char) *ap++; + break; + case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t) gprData[iCount++]; + else + dp->val.wc = (wchar_t) *ap++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex,info,dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* AIX */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp new file mode 100644 index 000000000..08eb557ab --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp @@ -0,0 +1,172 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if defined(AIX) + +/* + For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters + arrive in a separate chunk of data that has been loaded from the registers. + The args pointer has been set to the start of the parameters BEYOND the ones + arriving in registers +*/ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args, uint64_t *gprData, double *fprData) +{ + +#define PARAM_BUFFER_COUNT 16 +#define PARAM_GPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint64_t* ap = args; + uint32_t iCount = 0; + uint32_t fpCount = 0; + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*) gprData[iCount++]; + else + dp->val.p = (void*) *ap++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t) gprData[iCount++]; + else + dp->val.i8 = (int8_t) *ap++; + break; + case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t) gprData[iCount++]; + else + dp->val.i16 = (int16_t) *ap++; + break; + case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t) gprData[iCount++]; + else + dp->val.i32 = (int32_t) *ap++; + break; + case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t) gprData[iCount++]; + else + dp->val.i64 = (int64_t) *ap++; + break; + case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t) gprData[iCount++]; + else + dp->val.u8 = (uint8_t) *ap++; + break; + case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t) gprData[iCount++]; + else + dp->val.u16 = (uint16_t) *ap++; + break; + case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t) gprData[iCount++]; + else + dp->val.u32 = (uint32_t) *ap++; + break; + case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t) gprData[iCount++]; + else + dp->val.u64 = (uint64_t) *ap++; + break; + case nsXPTType::T_FLOAT : if (fpCount < 13) { + dp->val.f = (float) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else + dp->val.f = *((float*) ap++); + break; + case nsXPTType::T_DOUBLE : if (fpCount < 13) { + dp->val.d = (double) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else { + dp->val.f = *((double*) ap); + ap += 2; + } + break; + case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT) + dp->val.b = (bool) gprData[iCount++]; + else + dp->val.b = (bool) *ap++; + break; + case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char) gprData[iCount++]; + else + dp->val.c = (char) *ap++; + break; + case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t) gprData[iCount++]; + else + dp->val.wc = (wchar_t) *ap++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex,info,dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* AIX */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp new file mode 100644 index 000000000..86405a8ca --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp @@ -0,0 +1,220 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +#include "xptcprivate.h" +#include "xptiprivate.h" + +// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral +// parameters and the first 8 floating point parameters in registers +// (r3-r10 and f1-f8), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. The stack pointer has to retain 16-byte alignment, longlongs +// and doubles are aligned on 8-byte boundaries. +#ifndef __NO_FPRS__ +#define PARAM_BUFFER_COUNT 16 +#define GPR_COUNT 8 +#define FPR_COUNT 8 +#else +#define PARAM_BUFFER_COUNT 8 +#define GPR_COUNT 8 +#endif +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gprData[]' contains the arguments passed in integer registers +// - 'fprData[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint32_t* args, + uint32_t *gprData, + double *fprData) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info = nullptr; + uint32_t paramCount; + uint32_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (! dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint32_t* ap = args; + uint32_t gpr = 1; // skip one GPR register +#ifndef __NO_FPRS__ + uint32_t fpr = 0; +#endif + uint32_t tempu32; + uint64_t tempu64; + + for(i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + dp->val.d = fprData[fpr++]; +#else + if (gpr & 1) + gpr++; + if (gpr + 1 < GPR_COUNT) { + dp->val.d = *(double*) &gprData[gpr]; + gpr += 2; + } +#endif + else { + if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack + dp->val.d = *(double*) ap; + ap += 2; + } + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles +#else + if (gpr < GPR_COUNT) + dp->val.f = *(float*) &gprData[gpr++]; +#endif + else + dp->val.f = *(float*) ap++; + continue; + } + else if (!param.IsOut() && (type == nsXPTType::T_I64 + || type == nsXPTType::T_U64)) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + if ((gpr + 1) < GPR_COUNT) { + tempu64 = *(uint64_t*) &gprData[gpr]; + gpr += 2; + } + else { + if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack + tempu64 = *(uint64_t*) ap; + ap += 2; + } + } + else { + if (gpr < GPR_COUNT) + tempu32 = gprData[gpr++]; + else + tempu32 = *ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) tempu32); + else + dp->val.p = (void*) tempu32; + continue; + } + + switch(type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break; + case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break; + case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, + info, + dispatchParams); + + if (dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +// Load r11 with the constant 'n' and branch to SharedStub(). +// +// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; +// however, it's quick, dirty, and'll break when the ABI changes on +// us, which is what we want ;-). + +// gcc-3 version +// +// As G++3 ABI contains the length of the functionname in the mangled +// name, it is difficult to get a generic assembler mechanism like +// in the G++ 2.95 case. +// Create names would be like: +// _ZN14nsXPTCStubBase5Stub1Ev +// _ZN14nsXPTCStubBase6Stub12Ev +// _ZN14nsXPTCStubBase7Stub123Ev +// _ZN14nsXPTCStubBase8Stub1234Ev +// etc. +// Use assembler directives to get the names right... + +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub@local \n" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp new file mode 100644 index 000000000..ec359fc99 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp @@ -0,0 +1,185 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +#include "xptcprivate.h" + +// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral +// parameters and the first 8 floating point parameters in registers +// (r3-r10 and f1-f8), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. The stack pointer has to retain 16-byte alignment, longlongs +// and doubles are aligned on 8-byte boundaries. + +#define PARAM_BUFFER_COUNT 16 +#define GPR_COUNT 8 +#define FPR_COUNT 8 + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gprData[]' contains the arguments passed in integer registers +// - 'fprData[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint32_t* args, + uint32_t *gprData, + double *fprData) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + nsIInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + if (! iface_info) + return NS_ERROR_UNEXPECTED; + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (! dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint32_t* ap = args; + uint32_t gpr = 1; // skip one GPR register + uint32_t fpr = 0; + uint32_t tempu32; + uint64_t tempu64; + + for(i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (fpr < FPR_COUNT) + dp->val.d = fprData[fpr++]; + else { + if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack + dp->val.d = *(double*) ap; + ap += 2; + if (gpr < GPR_COUNT) + gpr += 2; + } + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (fpr < FPR_COUNT) + dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles + else { + dp->val.f = *(float*) ap; + ap += 1; + if (gpr < GPR_COUNT) + gpr += 1; + } + continue; + } + else if (!param.IsOut() && (type == nsXPTType::T_I64 + || type == nsXPTType::T_U64)) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + if ((gpr + 1) < GPR_COUNT) { + tempu64 = *(uint64_t*) &gprData[gpr]; + gpr += 2; + } + else { + if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack + tempu64 = *(uint64_t*) ap; + ap += 2; + } + } + else { + if (gpr < GPR_COUNT) + tempu32 = gprData[gpr++]; + else + tempu32 = *ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) tempu32); + else + dp->val.p = (void*) tempu32; + continue; + } + + switch(type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break; + case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break; + case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->CallMethod((uint16_t) methodIndex, info, dispatchParams); + + NS_RELEASE(iface_info); + + if (dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +// Load r11 with the constant 'n' and branch to SharedStub(). +// +// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; +// however, it's quick, dirty, and'll break when the ABI changes on +// us, which is what we want ;-). + +#define STUB_ENTRY(n) \ +__asm__ ( \ + ".section \".text\" \n\t" \ + ".align 2 \n\t" \ + ".globl Stub"#n"__14nsXPTCStubBase \n\t" \ + ".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \ + \ +"Stub"#n"__14nsXPTCStubBase: \n\t" \ + "li 11,"#n" \n\t" \ + "b SharedStub@local \n" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp new file mode 100644 index 000000000..62a693643 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp @@ -0,0 +1,202 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +#include "xptcprivate.h" +#include "xptiprivate.h" + +// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral +// parameters and the first 8 floating point parameters in registers +// (r3-r10 and f1-f8), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. The stack pointer has to retain 16-byte alignment, longlongs +// and doubles are aligned on 8-byte boundaries. + +#define PARAM_BUFFER_COUNT 16 +#define GPR_COUNT 8 +#define FPR_COUNT 8 + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gprData[]' contains the arguments passed in integer registers +// - 'fprData[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint32_t* args, + uint32_t *gprData, + double *fprData) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info = nullptr; + uint32_t paramCount; + uint32_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint32_t* ap = args; + uint32_t gpr = 1; // skip one GPR register + uint32_t fpr = 0; + uint32_t tempu32; + uint64_t tempu64; + + for(i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (fpr < FPR_COUNT) + dp->val.d = fprData[fpr++]; + else { + if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack + dp->val.d = *(double*) ap; + ap += 2; + } + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (fpr < FPR_COUNT) + dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles + else + dp->val.f = *(float*) ap++; + continue; + } + else if (!param.IsOut() && (type == nsXPTType::T_I64 + || type == nsXPTType::T_U64)) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + if ((gpr + 1) < GPR_COUNT) { + tempu64 = *(uint64_t*) &gprData[gpr]; + gpr += 2; + } + else { + if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack + tempu64 = *(uint64_t*) ap; + ap += 2; + } + } + else { + if (gpr < GPR_COUNT) + tempu32 = gprData[gpr++]; + else + tempu32 = *ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) tempu32); + else + dp->val.p = (void*) tempu32; + continue; + } + + switch(type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break; + case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break; + case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, + info, + dispatchParams); + + if (dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +// Load r11 with the constant 'n' and branch to SharedStub(). +// +// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; +// however, it's quick, dirty, and'll break when the ABI changes on +// us, which is what we want ;-). + + +// gcc-3 version +// +// As G++3 ABI contains the length of the functionname in the mangled +// name, it is difficult to get a generic assembler mechanism like +// in the G++ 2.95 case. +// Create names would be like: +// _ZN14nsXPTCStubBase5Stub1Ev +// _ZN14nsXPTCStubBase6Stub12Ev +// _ZN14nsXPTCStubBase7Stub123Ev +// _ZN14nsXPTCStubBase8Stub1234Ev +// etc. +// Use assembler directives to get the names right... + +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub@local \n" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp new file mode 100644 index 000000000..4c485a275 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp @@ -0,0 +1,165 @@ +/* -*- Mode: C -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +/* Under the Mac OS X PowerPC ABI, the first 8 integer and 13 floating point + * parameters are delivered in registers and are not on the stack, although + * stack space is allocated for them. The integer parameters are delivered + * in GPRs r3 through r10. The first 8 words of the parameter area on the + * stack shadow these registers. A word will either be in a register or on + * the stack, but not in both. Although the first floating point parameters + * are passed in floating point registers, GPR space and stack space is + * reserved for them as well. + * + * SharedStub has passed pointers to the parameter section of the stack + * and saved copies of the GPRs and FPRs used for parameter passing. We + * don't care about the first parameter (which is delivered here as the self + * pointer), so SharedStub pointed us past that. argsGPR thus points to GPR + * r4 (corresponding to the first argument after the self pointer) and + * argsStack points to the parameter section of the caller's stack frame + * reserved for the same argument. This way, it is possible to reference + * either argsGPR or argsStack with the same index. + * + * Contrary to the assumption made by the previous implementation, the + * Mac OS X PowerPC ABI doesn't impose any special alignment restrictions on + * parameter sections of stacks. Values that are 64 bits wide appear on the + * stack without any special padding. + * + * See also xptcstubs_asm_ppc_darwin.s.m4:_SharedStub. + * + * ABI reference: + * http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + * MachORuntime/PowerPCConventions/chapter_3_section_1.html */ + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch( + nsXPTCStubBase *self, + uint32_t methodIndex, + uint32_t *argsStack, + uint32_t *argsGPR, + double *argsFPR) { +#define PARAM_BUFFER_COUNT 16 +#define PARAM_FPR_COUNT 13 +#define PARAM_GPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant *dispatchParams = nullptr; + const nsXPTMethodInfo *methodInfo; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + uint32_t argIndex = 0; + uint32_t fprIndex = 0; + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; + + NS_ASSERTION(self, "no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &methodInfo); + NS_ASSERTION(methodInfo, "no method info"); + + paramCount = methodInfo->GetParamCount(); + + if(paramCount > PARAM_BUFFER_COUNT) { + dispatchParams = new nsXPTCMiniVariant[paramCount]; + } + else { + dispatchParams = paramBuffer; + } + NS_ASSERTION(dispatchParams,"no place for params"); + + for(i = 0; i < paramCount; i++, argIndex++) { + const nsXPTParamInfo ¶m = methodInfo->GetParam(i); + const nsXPTType &type = param.GetType(); + nsXPTCMiniVariant *dp = &dispatchParams[i]; + uint32_t theParam; + + if(argIndex < PARAM_GPR_COUNT) + theParam = argsGPR[argIndex]; + else + theParam = argsStack[argIndex]; + + if(param.IsOut() || !type.IsArithmetic()) + dp->val.p = (void *) theParam; + else { + switch(type) { + case nsXPTType::T_I8: + dp->val.i8 = (int8_t) theParam; + break; + case nsXPTType::T_I16: + dp->val.i16 = (int16_t) theParam; + break; + case nsXPTType::T_I32: + dp->val.i32 = (int32_t) theParam; + break; + case nsXPTType::T_U8: + dp->val.u8 = (uint8_t) theParam; + break; + case nsXPTType::T_U16: + dp->val.u16 = (uint16_t) theParam; + break; + case nsXPTType::T_U32: + dp->val.u32 = (uint32_t) theParam; + break; + case nsXPTType::T_I64: + case nsXPTType::T_U64: + ((DU *)dp)->hi = (uint32_t) theParam; + if(++argIndex < PARAM_GPR_COUNT) + ((DU *)dp)->lo = (uint32_t) argsGPR[argIndex]; + else + ((DU *)dp)->lo = (uint32_t) argsStack[argIndex]; + break; + case nsXPTType::T_BOOL: + dp->val.b = (bool) theParam; + break; + case nsXPTType::T_CHAR: + dp->val.c = (char) theParam; + break; + case nsXPTType::T_WCHAR: + dp->val.wc = (wchar_t) theParam; + break; + case nsXPTType::T_FLOAT: + if(fprIndex < PARAM_FPR_COUNT) + dp->val.f = (float) argsFPR[fprIndex++]; + else + dp->val.f = *(float *) &argsStack[argIndex]; + break; + case nsXPTType::T_DOUBLE: + if(fprIndex < PARAM_FPR_COUNT) + dp->val.d = argsFPR[fprIndex++]; + else + dp->val.d = *(double *) &argsStack[argIndex]; + argIndex++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + } + + result = self->mOuter-> + CallMethod((uint16_t)methodIndex, methodInfo, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp new file mode 100644 index 000000000..b8a09c97e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args) +{ + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint64_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_BOOL : dp->val.b = *((int64_t*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint64_t*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int64_t*) ap); break; + case nsXPTType::T_I8 : dp->val.i8 = *((int64_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int64_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int64_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint64_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint64_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint64_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*) ap); break; + case nsXPTType::T_FLOAT : dp->val.f = ((float*) ap)[1]; break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp new file mode 100644 index 000000000..22bf94d49 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp @@ -0,0 +1,117 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + nsIInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) *ap); + else + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_DOUBLE : + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi; + ((DU *)dp)->lo = ((DU *)ap)->lo; + ap++; + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + NS_RELEASE(iface_info); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp new file mode 100644 index 000000000..55d814b85 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp @@ -0,0 +1,120 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + nsIInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) *ap); + else + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_DOUBLE : + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi; + ((DU *)dp)->lo = ((DU *)ap)->lo; + ap++; + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + NS_RELEASE(iface_info); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp new file mode 100644 index 000000000..61f3df4ff --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp @@ -0,0 +1,112 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) *ap); + else + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_DOUBLE : + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi; + ((DU *)dp)->lo = ((DU *)ap)->lo; + ap++; + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp new file mode 100644 index 000000000..583ce9864 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args) +{ + +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint64_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int64_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int64_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int64_t*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint64_t*)ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint64_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint64_t*)ap); break; + case nsXPTType::T_FLOAT : dp->val.f = ((float*) ap)[1]; break; + case nsXPTType::T_BOOL : dp->val.b = *((uint64_t*)ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint64_t*)ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int64_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp new file mode 100644 index 000000000..ae058567f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp @@ -0,0 +1,190 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +// Keep this in sync with the linux version. + +#include "xptcprivate.h" +#include "xptiprivate.h" + +// The Darwin/x86-64 ABI passes the first 6 integer parameters and the +// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx, +// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. + +const uint32_t PARAM_BUFFER_COUNT = 16; +const uint32_t GPR_COUNT = 6; +const uint32_t FPR_COUNT = 8; + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gpregs[]' contains the arguments passed in integer registers +// - 'fpregs[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gpregs, double *fpregs) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if (paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip one GPR register for 'that' + uint32_t nr_fpr = 0; + uint64_t value; + + for (i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.d = *(double*) ap++; + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.f = *(float*) ap++; + continue; + } + else { + if (nr_gpr < GPR_COUNT) + value = gpregs[nr_gpr++]; + else + value = *ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*) value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break; + // Cast to uint8_t first, to remove garbage on upper 56 bits. + case nsXPTType::T_BOOL: dp->val.b = (bool)(uint8_t) value; break; + case nsXPTType::T_CHAR: dp->val.c = (char) value; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams); + + if (dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +// Darwin/x86-64 uses gcc >= 4.2 + +#define STUB_ENTRY(n) \ +asm(".section __TEXT,__text\n\t" \ + ".align 3\n\t" \ + ".if " #n " < 10\n\t" \ + ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + "__ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + "__ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 1000\n\t" \ + ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + "__ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \ + ".else\n\t" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ + ".endif\n\t" \ + "movl $" #n ", %eax\n\t" \ + "jmp SharedStub\n\t"); + +// static nsresult SharedStub(uint32_t methodIndex) +asm(".section __TEXT,__text\n\t" + ".align 3\n\t" + "SharedStub:\n\t" + // make room for gpregs (48), fpregs (64) + "pushq %rbp\n\t" + "movq %rsp,%rbp\n\t" + "subq $112,%rsp\n\t" + // save GP registers + "movq %rdi,-112(%rbp)\n\t" + "movq %rsi,-104(%rbp)\n\t" + "movq %rdx, -96(%rbp)\n\t" + "movq %rcx, -88(%rbp)\n\t" + "movq %r8 , -80(%rbp)\n\t" + "movq %r9 , -72(%rbp)\n\t" + "leaq -112(%rbp),%rcx\n\t" + // save FP registers + "movsd %xmm0,-64(%rbp)\n\t" + "movsd %xmm1,-56(%rbp)\n\t" + "movsd %xmm2,-48(%rbp)\n\t" + "movsd %xmm3,-40(%rbp)\n\t" + "movsd %xmm4,-32(%rbp)\n\t" + "movsd %xmm5,-24(%rbp)\n\t" + "movsd %xmm6,-16(%rbp)\n\t" + "movsd %xmm7, -8(%rbp)\n\t" + "leaq -64(%rbp),%r8\n\t" + // rdi has the 'self' pointer already + "movl %eax,%esi\n\t" + "leaq 16(%rbp),%rdx\n\t" + "call _PrepareAndDispatch\n\t" + "leave\n\t" + "ret\n\t"); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp new file mode 100644 index 000000000..01044363b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp @@ -0,0 +1,204 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +// Keep this in sync with the darwin version. + +#include "xptcprivate.h" +#include "xptiprivate.h" + +// The Linux/x86-64 ABI passes the first 6 integer parameters and the +// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx, +// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. + +const uint32_t PARAM_BUFFER_COUNT = 16; +const uint32_t GPR_COUNT = 6; +const uint32_t FPR_COUNT = 8; + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gpregs[]' contains the arguments passed in integer registers +// - 'fpregs[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gpregs, double *fpregs) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if (paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip one GPR register for 'that' + uint32_t nr_fpr = 0; + uint64_t value; + + for (i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.d = *(double*) ap++; + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.f = *(float*) ap++; + continue; + } + else { + if (nr_gpr < GPR_COUNT) + value = gpregs[nr_gpr++]; + else + value = *ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*) value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break; + // Cast to uint8_t first, to remove garbage on upper 56 bits. + case nsXPTType::T_BOOL: dp->val.b = (bool)(uint8_t) value; break; + case nsXPTType::T_CHAR: dp->val.c = (char) value; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams); + + if (dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +// Linux/x86-64 uses gcc >= 3.1 +#define STUB_ENTRY(n) \ +asm(".section \".text\"\n\t" \ + ".align 2\n\t" \ + ".if " #n " < 10\n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + ".hidden _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + ".type _ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \ + "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + ".hidden _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + ".type _ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \ + "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 1000\n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + ".hidden _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + ".type _ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \ + "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \ + ".else\n\t" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ + ".endif\n\t" \ + "movl $" #n ", %eax\n\t" \ + "jmp SharedStub\n\t" \ + ".if " #n " < 10\n\t" \ + ".size _ZN14nsXPTCStubBase5Stub" #n "Ev,.-_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".size _ZN14nsXPTCStubBase6Stub" #n "Ev,.-_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + ".else\n\t" \ + ".size _ZN14nsXPTCStubBase7Stub" #n "Ev,.-_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + ".endif"); + +// static nsresult SharedStub(uint32_t methodIndex) +asm(".section \".text\"\n\t" + ".align 2\n\t" + ".type SharedStub,@function\n\t" + "SharedStub:\n\t" + // make room for gpregs (48), fpregs (64) + "pushq %rbp\n\t" + "movq %rsp,%rbp\n\t" + "subq $112,%rsp\n\t" + // save GP registers + "movq %rdi,-112(%rbp)\n\t" + "movq %rsi,-104(%rbp)\n\t" + "movq %rdx, -96(%rbp)\n\t" + "movq %rcx, -88(%rbp)\n\t" + "movq %r8 , -80(%rbp)\n\t" + "movq %r9 , -72(%rbp)\n\t" + "leaq -112(%rbp),%rcx\n\t" + // save FP registers + "movsd %xmm0,-64(%rbp)\n\t" + "movsd %xmm1,-56(%rbp)\n\t" + "movsd %xmm2,-48(%rbp)\n\t" + "movsd %xmm3,-40(%rbp)\n\t" + "movsd %xmm4,-32(%rbp)\n\t" + "movsd %xmm5,-24(%rbp)\n\t" + "movsd %xmm6,-16(%rbp)\n\t" + "movsd %xmm7, -8(%rbp)\n\t" + "leaq -64(%rbp),%r8\n\t" + // rdi has the 'self' pointer already + "movl %eax,%esi\n\t" + "leaq 16(%rbp),%rdx\n\t" + "call PrepareAndDispatch@plt\n\t" + "leave\n\t" + "ret\n\t" + ".size SharedStub,.-SharedStub"); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp new file mode 100644 index 000000000..677fa9960 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp @@ -0,0 +1,139 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +// Keep this in sync with the darwin version. + +#include "xptcprivate.h" +#include "xptiprivate.h" + +// The Linux/x86-64 ABI passes the first 6 integer parameters and the +// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx, +// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. + +const uint32_t PARAM_BUFFER_COUNT = 16; +const uint32_t GPR_COUNT = 6; +const uint32_t FPR_COUNT = 8; + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gpregs[]' contains the arguments passed in integer registers +// - 'fpregs[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gpregs, double *fpregs) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if (paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + if (!dispatchParams) + return NS_ERROR_OUT_OF_MEMORY; + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip one GPR register for 'that' + uint32_t nr_fpr = 0; + uint64_t value; + + for (i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.d = *(double*) ap++; + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.f = *(float*) ap++; + continue; + } + else { + if (nr_gpr < GPR_COUNT) + value = gpregs[nr_gpr++]; + else + value = *ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*) value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break; + // Cast to uint8_t first, to remove garbage on upper 56 bits. + case nsXPTType::T_BOOL: dp->val.b = (bool)(uint8_t) value; break; + case nsXPTType::T_CHAR: dp->val.c = (char) value; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams); + + if (dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp new file mode 100644 index 000000000..39eec5e54 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + dp->val.p = (void*) *ap; + switch(type) + { + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/win32/moz.build b/xpcom/reflect/xptcall/md/win32/moz.build new file mode 100644 index 000000000..5dbe41d76 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/moz.build @@ -0,0 +1,45 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG['TARGET_CPU'] == 'x86_64': + if CONFIG['GNU_CXX']: + SOURCES += [ + 'xptcinvoke_x86_64.cpp', + 'xptcstubs_x86_64_gnu.cpp', + ] + SOURCES += [ + 'xptcinvoke_asm_x86_64_gnu.s' + ] + else: + SOURCES += [ + 'xptcinvoke_x86_64.cpp', + 'xptcstubs_x86_64.cpp' + ] + SOURCES += [ + 'xptcinvoke_asm_x86_64.asm', + 'xptcstubs_asm_x86_64.asm' + ] +else: + if CONFIG['GNU_CXX']: + SOURCES += [ + 'xptcinvoke_x86_gnu.cpp', + 'xptcstubs.cpp', + ] + else: + SOURCES += [ + 'xptcinvoke.cpp', + 'xptcinvoke_asm_x86_msvc.asm', + 'xptcstubs.cpp', + ] + SOURCES['xptcinvoke.cpp'].no_pgo = True + SOURCES['xptcinvoke_asm_x86_msvc.asm'].flags += ['-safeseh'] + +FINAL_LIBRARY = 'xul' + +LOCAL_INCLUDES += [ + '../..', + '/xpcom/reflect/xptinfo', +] diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp new file mode 100644 index 000000000..faec869f6 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#ifndef WIN32 +#error "This code is for Win32 only" +#endif + +extern "C" void __fastcall +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(; paramCount > 0; paramCount--, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm new file mode 100644 index 000000000..bf7c2ef0c --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm @@ -0,0 +1,107 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + +extrn invoke_copy_to_stack:PROC + + +.CODE + +; +;XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params) +; + +XPTC__InvokebyIndex PROC FRAME + + ; store register parameters + + mov qword ptr [rsp+32], r9 ; params + mov dword ptr [rsp+24], r8d ; paramCount + mov dword ptr [rsp+16], edx ; methodIndex + mov qword ptr [rsp+8], rcx ; that + + push rbp + .PUSHREG rbp + mov rbp, rsp ; store current RSP to RBP + .SETFRAME rbp, 0 + .ENDPROLOG + + sub rsp, 32 + + ; maybe we don't have any parameters to copy + + test r8d, r8d + jz noparams + + ; + ; Build stack for stdcall + ; + + ; 1st parameter is space for parameters + + mov eax, r8d + or eax, 1 + shl rax, 3 ; *= 8 + sub rsp, rax + mov rcx, rsp + + ; 2nd parameter is parameter count + + mov edx, r8d + + ; 3rd parameter is params + + mov r8, r9 + + sub rsp, 40 + call invoke_copy_to_stack ; rcx = d + ; edx = paramCount + ; r8 = s + add rsp, 32 + + ; Current stack is the following. + ; + ; 0h: [space (for this)] + ; 8h: [1st parameter] + ; 10h: [2nd parameter] + ; 18h: [3rd parameter] + ; 20h: [4th parameter] + ; ... + ; + ; On Win64 ABI, the first 4 parameters are passed using registers, + ; and others are on stack. + + ; 1st, 2nd and 3rd arguments are passed via registers + + mov rdx, qword ptr [rsp+8] ; 1st parameter + movsd xmm1, qword ptr [rsp+8] ; for double + + mov r8, qword ptr [rsp+16] ; 2nd parameter + movsd xmm2, qword ptr [rsp+16] ; for double + + mov r9, qword ptr [rsp+24] ; 3rd parameter + movsd xmm3, qword ptr [rsp+24] ; for double + + ; rcx register is this + + mov rcx, qword ptr [rbp+8+8] ; that + +noparams: + + ; calculate call address + + mov r11, qword ptr [rcx] + mov eax, dword ptr [rbp+16+8] ; methodIndex + + call qword ptr [r11+rax*8] ; stdcall, i.e. callee cleans up stack. + + mov rsp, rbp + pop rbp + + ret + +XPTC__InvokebyIndex ENDP + + +END diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s new file mode 100644 index 000000000..006e0444b --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s @@ -0,0 +1,110 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.extern invoke_copy_to_stack + + +.text +.intel_syntax noprefix + +# +#_XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.globl XPTC__InvokebyIndex +.def XPTC__InvokebyIndex + .scl 3 + .type 46 +.endef +XPTC__InvokebyIndex: + + # store register parameters + + mov qword ptr [rsp+32], r9 # params + mov dword ptr [rsp+24], r8d # paramCount + mov dword ptr [rsp+16], edx # methodIndex + mov qword ptr [rsp+8], rcx # that + + push rbp + # .PUSHREG rbp + mov rbp, rsp # store current RSP to RBP + # .SETFRAME rbp, 0 + # .ENDPROLOG + + sub rsp, 32 + + # maybe we don't have any parameters to copy + + test r8d, r8d + jz noparams + + # + # Build stack for stdcall + # + + # 1st parameter is space for parameters + + mov eax, r8d + or eax, 1 + shl rax, 3 # *= 8 + sub rsp, rax + mov rcx, rsp + + # 2nd parameter is parameter count + + mov edx, r8d + + # 3rd parameter is params + + mov r8, r9 + + sub rsp, 40 + call invoke_copy_to_stack # rcx = d + # edx = paramCount + # r8 = s + add rsp, 32 + + # Current stack is the following. + # + # 0h: [space (for this)] + # 8h: [1st parameter] + # 10h: [2nd parameter] + # 18h: [3rd parameter] + # 20h: [4th parameter] + # ... + # + # On Win64 ABI, the first 4 parameters are passed using registers, + # and others are on stack. + + # 1st, 2nd and 3rd arguments are passed via registers + + mov rdx, qword ptr [rsp+8] # 1st parameter + movsd xmm1, qword ptr [rsp+8] # for double + + mov r8, qword ptr [rsp+16] # 2nd parameter + movsd xmm2, qword ptr [rsp+16] # for double + + mov r9, qword ptr [rsp+24] # 3rd parameter + movsd xmm3, qword ptr [rsp+24] # for double + + # rcx register is this + + mov rcx, qword ptr [rbp+8+8] # that + +noparams: + + # calculate call address + + mov r11, qword ptr [rcx] + mov eax, dword ptr [rbp+16+8] # methodIndex + + call qword ptr [r11+rax*8] # stdcall, i.e. callee cleans up stack. + + mov rsp, rbp + pop rbp + + ret + + diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm new file mode 100644 index 000000000..f3b7a1826 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm @@ -0,0 +1,63 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + + TITLE xptcinvoke_asm_x86_msvc.asm + .686P + .model flat + +PUBLIC _NS_InvokeByIndex +EXTRN @invoke_copy_to_stack@12:PROC + +; +; extern "C" nsresult __cdecl +; NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params) +; + +_TEXT SEGMENT +_NS_InvokeByIndex PROC + + ; Build frame + push ebp + mov ebp, esp + + ; Save paramCount for later + mov edx, dword ptr [ebp+16] + + ; Do we have any parameters? + test edx, edx + jz noparams + + ; Build call for copy_to_stack, which is __fastcall + + ; Allocate space for parameters. 8 is the biggest size + ; any parameter can be, so assume that all our parameters + ; are that large. + mov eax, edx + shl eax, 3 + sub esp, eax + + mov ecx, esp + push dword ptr [ebp+20] + call @invoke_copy_to_stack@12 +noparams: + ; Push the `this' parameter for the call. + mov ecx, dword ptr [ebp+8] + push ecx + + ; Load the vtable. + mov edx, dword ptr [ecx] + + ; Call the vtable index at `methodIndex'. + mov eax, dword ptr [ebp+12] + call dword ptr [edx+eax*4] + + ; Reset and return. + mov esp, ebp + pop ebp + ret +_NS_InvokeByIndex ENDP +_TEXT ENDS + +END diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp new file mode 100644 index 000000000..36b454b35 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +extern "C" void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(; paramCount > 0; paramCount--, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + + /* + * AMD64 platform uses 8 bytes align. + */ + + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" nsresult +XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +extern "C" +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return XPTC__InvokebyIndex(that, methodIndex, paramCount, params); +} + diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp new file mode 100644 index 000000000..0e73e99f3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp @@ -0,0 +1,106 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +extern "C" { +void __attribute__ ((__used__)) __attribute__ ((regparm(3))) +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d) +{ + for(uint32_t i = paramCount; i >0; i--, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} +} // extern "C" + +/* + EXPORT_XPCOM_API(nsresult) + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + + Each param takes at most two 4-byte words. + It doesn't matter if we push too many words, and calculating the exact + amount takes time. + + that = ebp + 0x08 + methodIndex = ebp + 0x0c + paramCount = ebp + 0x10 + params = ebp + 0x14 + +*/ + +__asm__ ( + ".text\n\t" +/* alignment here seems unimportant here; this was 16, now it's 2 which + is what xptcstubs uses. */ + ".align 2\n\t" + ".globl _NS_InvokeByIndex\n\t" + "_NS_InvokeByIndex:\n\t" + "pushl %ebp\n\t" + "movl %esp, %ebp\n\t" + "movl 0x10(%ebp), %eax\n\t" + "leal 0(,%eax,8),%edx\n\t" + + /* set up call frame for method. */ + "subl %edx, %esp\n\t" /* make room for params. */ +/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size. + * This is to avoid protection faults where SSE+ alignment of stack pointer + * is assumed and required, e.g. by GCC4's -ftree-vectorize option. + */ + "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */ +/* $esp should be aligned to a 16-byte boundary here (note we include an + * additional 4 bytes in a later push instruction). This will ensure $ebp + * in the function called below is aligned to a 0x8 boundary. SSE instructions + * like movapd/movdqa expect memory operand to be aligned on a 16-byte + * boundary. The GCC compiler will generate the memory operand using $ebp + * with an 8-byte offset. + */ + "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */ + "movl %esp, %ecx\n\t" /* ecx = d */ + "movl 8(%ebp), %edx\n\t" /* edx = this */ + "pushl %edx\n\t" /* push this. esp % 16 == 0 */ + + "movl 0x14(%ebp), %edx\n\t" + "call _invoke_copy_to_stack\n\t" + "movl 0x08(%ebp), %ecx\n\t" /* 'that' */ + "movl (%ecx), %edx\n\t" + "movl 0x0c(%ebp), %eax\n\t" /* function index */ + "leal (%edx,%eax,4), %edx\n\t" + "call *(%edx)\n\t" + "movl %ebp, %esp\n\t" + "popl %ebp\n\t" + "ret\n" + ".section .drectve\n\t" + ".ascii \" -export:NS_InvokeByIndex\"\n\t" + ".text\n\t" +); diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp new file mode 100644 index 000000000..e525aebd7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp @@ -0,0 +1,227 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +#ifndef WIN32 +#error "This code is for Win32 only" +#endif + +extern "C" { + +#if !defined(__GNUC__) && !defined(__clang__) +static +#endif +nsresult __stdcall +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint32_t* args, uint32_t* stackBytesToPop) +{ +#define PARAM_BUFFER_COUNT 16 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + // If anything fails before stackBytesToPop can be set then + // the failure is completely catastrophic! + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + // setup variant array pointer + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + NS_ASSERTION(dispatchParams,"no place for params"); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + *stackBytesToPop = ((uint32_t)ap) - ((uint32_t)args); + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +} // extern "C" + +// declspec(naked) is broken in gcc and clang-cl +#if !defined(__GNUC__) && !defined(__clang__) +static +__declspec(naked) +void SharedStub(void) +{ + __asm { + push ebp // set up simple stack frame + mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args + push ecx // make room for a ptr + lea eax, [ebp-4] // pointer to stackBytesToPop + push eax + lea eax, [ebp+12] // pointer to args + push eax + push ecx // vtbl_index + mov eax, [ebp+8] // this + push eax + call PrepareAndDispatch + mov edx, [ebp+4] // return address + mov ecx, [ebp-4] // stackBytesToPop + add ecx, 8 // for 'this' and return address + mov esp, ebp + pop ebp + add esp, ecx // fix up stack pointer + jmp edx // simulate __stdcall return + } +} + +// these macros get expanded (many times) in the file #included below +#define STUB_ENTRY(n) \ +__declspec(naked) nsresult __stdcall nsXPTCStubBase::Stub##n() \ +{ __asm mov ecx, n __asm jmp SharedStub } + +#else + +asm(".text\n\t" + ".align 4\n\t" + "SharedStub:\n\t" + "push %ebp\n\t" + "mov %esp, %ebp\n\t" + "push %ecx\n\t" + "lea -4(%ebp), %eax\n\t" + "push %eax\n\t" + "lea 12(%ebp), %eax\n\t" + "push %eax\n\t" + "push %ecx\n\t" + "movl 8(%ebp), %eax\n\t" + "push %eax\n\t" + "call _PrepareAndDispatch@16\n\t" + "mov 4(%ebp), %edx\n\t" + "mov -4(%ebp), %ecx\n\t" + "add $8, %ecx\n\t" + "mov %ebp, %esp\n\t" + "pop %ebp\n\t" + "add %ecx, %esp\n\t" + "jmp *%edx" +); + +// The clang-cl specific code below is required because mingw uses the gcc name +// mangling, but clang-cl implements the MSVC name mangling. + +#ifdef __clang__ + +#define STUB_ENTRY(n) \ +asm(".text\n\t" \ + ".align 4\n\t" \ + ".globl \"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\"\n\t" \ + ".def \"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\"; \n\t" \ + ".scl 2\n\t" \ + ".type 46\n\t" \ + ".endef\n\t" \ + "\"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\":\n\t" \ + "mov $" #n ", %ecx\n\t" \ + "jmp SharedStub"); + +#else + +#define STUB_ENTRY(n) \ +asm(".text\n\t" \ + ".align 4\n\t" \ + ".if " #n " < 10\n\t" \ + ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev@4\n\t" \ + ".def __ZN14nsXPTCStubBase5Stub" #n "Ev@4; \n\t" \ + ".scl 3\n\t" \ + ".type 46\n\t" \ + ".endef\n\t" \ + "__ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \ + ".def __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \ + ".scl 3\n\t" \ + ".type 46\n\t" \ + ".endef\n\t" \ + "__ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n\t" \ + ".elseif " #n " < 1000\n\t" \ + ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \ + ".def __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \ + ".scl 3\n\t" \ + ".type 46\n\t" \ + ".endef\n\t" \ + "__ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n\t" \ + ".else\n\t" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ + ".endif\n\t" \ + "mov $" #n ", %ecx\n\t" \ + "jmp SharedStub"); + +#endif + +#endif /* __GNUC__ || __clang__ */ + +#define SENTINEL_ENTRY(n) \ +nsresult __stdcall nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#ifdef _MSC_VER +#pragma warning(disable : 4035) // OK to have no return value +#endif +#include "xptcstubsdef.inc" +#ifdef _MSC_VER +#pragma warning(default : 4035) // restore default +#endif + +void +#ifdef __GNUC__ +__cdecl +#endif +xptc_dummy() +{ +} diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm new file mode 100644 index 000000000..db2cc16be --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm @@ -0,0 +1,335 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + +extrn PrepareAndDispatch:PROC + +.code + +SharedStub PROC FRAME + sub rsp, 104 + .ALLOCSTACK 104 + .ENDPROLOG + + ; rcx is this pointer. Need backup for optimized build + + mov qword ptr [rsp+88], rcx + + ; + ; fist 4 parameters (1st is "this" pointer) are passed in registers. + ; + + ; for floating value + + movsd qword ptr [rsp+64], xmm1 + movsd qword ptr [rsp+72], xmm2 + movsd qword ptr [rsp+80], xmm3 + + ; for integer value + + mov qword ptr [rsp+40], rdx + mov qword ptr [rsp+48], r8 + mov qword ptr [rsp+56], r9 + + ; + ; Call PrepareAndDispatch function + ; + + ; 5th parameter (floating parameters) of PrepareAndDispatch + + lea r9, qword ptr [rsp+64] + mov qword ptr [rsp+32], r9 + + ; 4th parameter (normal parameters) of PrepareAndDispatch + + lea r9, qword ptr [rsp+40] + + ; 3rd parameter (pointer to args on stack) + + lea r8, qword ptr [rsp+40+104] + + ; 2nd parameter (vtbl_index) + + mov rdx, r11 + + ; 1st parameter (this) (rcx) + + call PrepareAndDispatch + + ; restore rcx + + mov rcx, qword ptr [rsp+88] + + ; + ; clean up register + ; + + add rsp, 104+8 + + ; set return address + + mov rdx, qword ptr [rsp-8] + + ; simulate __stdcall return + + jmp rdx + +SharedStub ENDP + + +STUBENTRY MACRO functionname, paramcount +functionname PROC + mov r11, paramcount + jmp SharedStub +functionname ENDP +ENDM + + STUBENTRY ?Stub3@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 3 + STUBENTRY ?Stub4@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 4 + STUBENTRY ?Stub5@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 5 + STUBENTRY ?Stub6@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 6 + STUBENTRY ?Stub7@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 7 + STUBENTRY ?Stub8@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 8 + STUBENTRY ?Stub9@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 9 + STUBENTRY ?Stub10@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 10 + STUBENTRY ?Stub11@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 11 + STUBENTRY ?Stub12@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 12 + STUBENTRY ?Stub13@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 13 + STUBENTRY ?Stub14@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 14 + STUBENTRY ?Stub15@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 15 + STUBENTRY ?Stub16@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 16 + STUBENTRY ?Stub17@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 17 + STUBENTRY ?Stub18@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 18 + STUBENTRY ?Stub19@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 19 + STUBENTRY ?Stub20@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 20 + STUBENTRY ?Stub21@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 21 + STUBENTRY ?Stub22@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 22 + STUBENTRY ?Stub23@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 23 + STUBENTRY ?Stub24@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 24 + STUBENTRY ?Stub25@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 25 + STUBENTRY ?Stub26@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 26 + STUBENTRY ?Stub27@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 27 + STUBENTRY ?Stub28@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 28 + STUBENTRY ?Stub29@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 29 + STUBENTRY ?Stub30@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 30 + STUBENTRY ?Stub31@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 31 + STUBENTRY ?Stub32@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 32 + STUBENTRY ?Stub33@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 33 + STUBENTRY ?Stub34@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 34 + STUBENTRY ?Stub35@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 35 + STUBENTRY ?Stub36@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 36 + STUBENTRY ?Stub37@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 37 + STUBENTRY ?Stub38@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 38 + STUBENTRY ?Stub39@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 39 + STUBENTRY ?Stub40@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 40 + STUBENTRY ?Stub41@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 41 + STUBENTRY ?Stub42@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 42 + STUBENTRY ?Stub43@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 43 + STUBENTRY ?Stub44@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 44 + STUBENTRY ?Stub45@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 45 + STUBENTRY ?Stub46@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 46 + STUBENTRY ?Stub47@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 47 + STUBENTRY ?Stub48@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 48 + STUBENTRY ?Stub49@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 49 + STUBENTRY ?Stub50@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 50 + STUBENTRY ?Stub51@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 51 + STUBENTRY ?Stub52@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 52 + STUBENTRY ?Stub53@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 53 + STUBENTRY ?Stub54@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 54 + STUBENTRY ?Stub55@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 55 + STUBENTRY ?Stub56@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 56 + STUBENTRY ?Stub57@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 57 + STUBENTRY ?Stub58@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 58 + STUBENTRY ?Stub59@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 59 + STUBENTRY ?Stub60@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 60 + STUBENTRY ?Stub61@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 61 + STUBENTRY ?Stub62@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 62 + STUBENTRY ?Stub63@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 63 + STUBENTRY ?Stub64@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 64 + STUBENTRY ?Stub65@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 65 + STUBENTRY ?Stub66@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 66 + STUBENTRY ?Stub67@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 67 + STUBENTRY ?Stub68@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 68 + STUBENTRY ?Stub69@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 69 + STUBENTRY ?Stub70@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 70 + STUBENTRY ?Stub71@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 71 + STUBENTRY ?Stub72@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 72 + STUBENTRY ?Stub73@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 73 + STUBENTRY ?Stub74@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 74 + STUBENTRY ?Stub75@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 75 + STUBENTRY ?Stub76@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 76 + STUBENTRY ?Stub77@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 77 + STUBENTRY ?Stub78@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 78 + STUBENTRY ?Stub79@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 79 + STUBENTRY ?Stub80@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 80 + STUBENTRY ?Stub81@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 81 + STUBENTRY ?Stub82@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 82 + STUBENTRY ?Stub83@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 83 + STUBENTRY ?Stub84@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 84 + STUBENTRY ?Stub85@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 85 + STUBENTRY ?Stub86@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 86 + STUBENTRY ?Stub87@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 87 + STUBENTRY ?Stub88@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 88 + STUBENTRY ?Stub89@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 89 + STUBENTRY ?Stub90@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 90 + STUBENTRY ?Stub91@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 91 + STUBENTRY ?Stub92@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 92 + STUBENTRY ?Stub93@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 93 + STUBENTRY ?Stub94@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 94 + STUBENTRY ?Stub95@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 95 + STUBENTRY ?Stub96@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 96 + STUBENTRY ?Stub97@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 97 + STUBENTRY ?Stub98@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 98 + STUBENTRY ?Stub99@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 99 + STUBENTRY ?Stub100@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 100 + STUBENTRY ?Stub101@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 101 + STUBENTRY ?Stub102@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 102 + STUBENTRY ?Stub103@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 103 + STUBENTRY ?Stub104@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 104 + STUBENTRY ?Stub105@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 105 + STUBENTRY ?Stub106@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 106 + STUBENTRY ?Stub107@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 107 + STUBENTRY ?Stub108@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 108 + STUBENTRY ?Stub109@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 109 + STUBENTRY ?Stub110@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 110 + STUBENTRY ?Stub111@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 111 + STUBENTRY ?Stub112@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 112 + STUBENTRY ?Stub113@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 113 + STUBENTRY ?Stub114@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 114 + STUBENTRY ?Stub115@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 115 + STUBENTRY ?Stub116@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 116 + STUBENTRY ?Stub117@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 117 + STUBENTRY ?Stub118@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 118 + STUBENTRY ?Stub119@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 119 + STUBENTRY ?Stub120@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 120 + STUBENTRY ?Stub121@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 121 + STUBENTRY ?Stub122@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 122 + STUBENTRY ?Stub123@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 123 + STUBENTRY ?Stub124@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 124 + STUBENTRY ?Stub125@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 125 + STUBENTRY ?Stub126@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 126 + STUBENTRY ?Stub127@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 127 + STUBENTRY ?Stub128@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 128 + STUBENTRY ?Stub129@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 129 + STUBENTRY ?Stub130@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 130 + STUBENTRY ?Stub131@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 131 + STUBENTRY ?Stub132@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 132 + STUBENTRY ?Stub133@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 133 + STUBENTRY ?Stub134@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 134 + STUBENTRY ?Stub135@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 135 + STUBENTRY ?Stub136@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 136 + STUBENTRY ?Stub137@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 137 + STUBENTRY ?Stub138@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 138 + STUBENTRY ?Stub139@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 139 + STUBENTRY ?Stub140@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 140 + STUBENTRY ?Stub141@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 141 + STUBENTRY ?Stub142@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 142 + STUBENTRY ?Stub143@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 143 + STUBENTRY ?Stub144@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 144 + STUBENTRY ?Stub145@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 145 + STUBENTRY ?Stub146@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 146 + STUBENTRY ?Stub147@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 147 + STUBENTRY ?Stub148@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 148 + STUBENTRY ?Stub149@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 149 + STUBENTRY ?Stub150@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 150 + STUBENTRY ?Stub151@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 151 + STUBENTRY ?Stub152@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 152 + STUBENTRY ?Stub153@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 153 + STUBENTRY ?Stub154@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 154 + STUBENTRY ?Stub155@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 155 + STUBENTRY ?Stub156@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 156 + STUBENTRY ?Stub157@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 157 + STUBENTRY ?Stub158@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 158 + STUBENTRY ?Stub159@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 159 + STUBENTRY ?Stub160@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 160 + STUBENTRY ?Stub161@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 161 + STUBENTRY ?Stub162@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 162 + STUBENTRY ?Stub163@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 163 + STUBENTRY ?Stub164@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 164 + STUBENTRY ?Stub165@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 165 + STUBENTRY ?Stub166@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 166 + STUBENTRY ?Stub167@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 167 + STUBENTRY ?Stub168@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 168 + STUBENTRY ?Stub169@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 169 + STUBENTRY ?Stub170@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 170 + STUBENTRY ?Stub171@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 171 + STUBENTRY ?Stub172@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 172 + STUBENTRY ?Stub173@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 173 + STUBENTRY ?Stub174@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 174 + STUBENTRY ?Stub175@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 175 + STUBENTRY ?Stub176@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 176 + STUBENTRY ?Stub177@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 177 + STUBENTRY ?Stub178@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 178 + STUBENTRY ?Stub179@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 179 + STUBENTRY ?Stub180@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 180 + STUBENTRY ?Stub181@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 181 + STUBENTRY ?Stub182@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 182 + STUBENTRY ?Stub183@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 183 + STUBENTRY ?Stub184@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 184 + STUBENTRY ?Stub185@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 185 + STUBENTRY ?Stub186@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 186 + STUBENTRY ?Stub187@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 187 + STUBENTRY ?Stub188@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 188 + STUBENTRY ?Stub189@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 189 + STUBENTRY ?Stub190@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 190 + STUBENTRY ?Stub191@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 191 + STUBENTRY ?Stub192@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 192 + STUBENTRY ?Stub193@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 193 + STUBENTRY ?Stub194@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 194 + STUBENTRY ?Stub195@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 195 + STUBENTRY ?Stub196@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 196 + STUBENTRY ?Stub197@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 197 + STUBENTRY ?Stub198@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 198 + STUBENTRY ?Stub199@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 199 + STUBENTRY ?Stub200@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 200 + STUBENTRY ?Stub201@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 201 + STUBENTRY ?Stub202@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 202 + STUBENTRY ?Stub203@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 203 + STUBENTRY ?Stub204@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 204 + STUBENTRY ?Stub205@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 205 + STUBENTRY ?Stub206@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 206 + STUBENTRY ?Stub207@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 207 + STUBENTRY ?Stub208@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 208 + STUBENTRY ?Stub209@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 209 + STUBENTRY ?Stub210@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 210 + STUBENTRY ?Stub211@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 211 + STUBENTRY ?Stub212@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 212 + STUBENTRY ?Stub213@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 213 + STUBENTRY ?Stub214@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 214 + STUBENTRY ?Stub215@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 215 + STUBENTRY ?Stub216@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 216 + STUBENTRY ?Stub217@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 217 + STUBENTRY ?Stub218@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 218 + STUBENTRY ?Stub219@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 219 + STUBENTRY ?Stub220@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 220 + STUBENTRY ?Stub221@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 221 + STUBENTRY ?Stub222@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 222 + STUBENTRY ?Stub223@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 223 + STUBENTRY ?Stub224@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 224 + STUBENTRY ?Stub225@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 225 + STUBENTRY ?Stub226@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 226 + STUBENTRY ?Stub227@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 227 + STUBENTRY ?Stub228@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 228 + STUBENTRY ?Stub229@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 229 + STUBENTRY ?Stub230@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 230 + STUBENTRY ?Stub231@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 231 + STUBENTRY ?Stub232@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 232 + STUBENTRY ?Stub233@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 233 + STUBENTRY ?Stub234@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 234 + STUBENTRY ?Stub235@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 235 + STUBENTRY ?Stub236@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 236 + STUBENTRY ?Stub237@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 237 + STUBENTRY ?Stub238@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 238 + STUBENTRY ?Stub239@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 239 + STUBENTRY ?Stub240@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 240 + STUBENTRY ?Stub241@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 241 + STUBENTRY ?Stub242@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 242 + STUBENTRY ?Stub243@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 243 + STUBENTRY ?Stub244@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 244 + STUBENTRY ?Stub245@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 245 + STUBENTRY ?Stub246@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 246 + STUBENTRY ?Stub247@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 247 + STUBENTRY ?Stub248@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 248 + STUBENTRY ?Stub249@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 249 + +END diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp new file mode 100644 index 000000000..8ff479d1e --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp @@ -0,0 +1,197 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +/* + * This is for Windows XP 64-Bit Edition / Server 2003 for AMD64 or later. + */ + +extern "C" nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, + uint64_t *gprData, double *fprData) +{ +#define PARAM_BUFFER_COUNT 16 +// +// "this" pointer is first parameter, so parameter count is 3. +// +#define PARAM_GPR_COUNT 3 +#define PARAM_FPR_COUNT 3 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + // + // setup variant array pointer + // + + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + + uint64_t* ap = args; + uint32_t iCount = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*)gprData[iCount++]; + else + dp->val.p = (void*)*ap++; + + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8: + if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t)gprData[iCount++]; + else + dp->val.i8 = *((int8_t*)ap++); + break; + + case nsXPTType::T_I16: + if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t)gprData[iCount++]; + else + dp->val.i16 = *((int16_t*)ap++); + break; + + case nsXPTType::T_I32: + if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t)gprData[iCount++]; + else + dp->val.i32 = *((int32_t*)ap++); + break; + + case nsXPTType::T_I64: + if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t)gprData[iCount++]; + else + dp->val.i64 = *((int64_t*)ap++); + break; + + case nsXPTType::T_U8: + if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t)gprData[iCount++]; + else + dp->val.u8 = *((uint8_t*)ap++); + break; + + case nsXPTType::T_U16: + if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t)gprData[iCount++]; + else + dp->val.u16 = *((uint16_t*)ap++); + break; + + case nsXPTType::T_U32: + if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t)gprData[iCount++]; + else + dp->val.u32 = *((uint32_t*)ap++); + break; + + case nsXPTType::T_U64: + if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t)gprData[iCount++]; + else + dp->val.u64 = *((uint64_t*)ap++); + break; + + case nsXPTType::T_FLOAT: + if (iCount < PARAM_FPR_COUNT) + // The value in xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = (double)fprData[iCount++]; + else + dp->val.f = *((float*)ap++); + break; + + case nsXPTType::T_DOUBLE: + if (iCount < PARAM_FPR_COUNT) + dp->val.d = (double)fprData[iCount++]; + else + dp->val.d = *((double*)ap++); + break; + + case nsXPTType::T_BOOL: + if (iCount < PARAM_GPR_COUNT) + // We need cast to uint8_t to remove garbage on upper 56-bit + // at first. + dp->val.b = (bool)(uint8_t)gprData[iCount++]; + else + dp->val.b = *((bool*)ap++); + break; + + case nsXPTType::T_CHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char)gprData[iCount++]; + else + dp->val.c = *((char*)ap++); + break; + + case nsXPTType::T_WCHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t)gprData[iCount++]; + else + dp->val.wc = *((wchar_t*)ap++); + break; + + default: + NS_ERROR("bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +#define STUB_ENTRY(n) /* defined in the assembly file */ + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +void +xptc_dummy() +{ +} + diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp new file mode 100644 index 000000000..2676334d2 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp @@ -0,0 +1,297 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" + +/* + * This is for Windows 64 bit (x86_64) using GCC syntax + * Code was copied from the MSVC version. + */ + +#if !defined(_AMD64_) || !defined(__GNUC__) +# error xptcstubs_x86_64_gnu.cpp being used unexpectedly +#endif + +extern "C" nsresult __attribute__((__used__)) +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gprData, double *fprData) +{ +#define PARAM_BUFFER_COUNT 16 +// +// "this" pointer is first parameter, so parameter count is 3. +// +#define PARAM_GPR_COUNT 3 +#define PARAM_FPR_COUNT 3 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = nullptr; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self, "no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info, "no method info"); + + paramCount = info->GetParamCount(); + + // + // setup variant array pointer + // + + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + + uint64_t* ap = args; + uint32_t iCount = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*)gprData[iCount++]; + else + dp->val.p = (void*)*ap++; + + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8: + if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t)gprData[iCount++]; + else + dp->val.i8 = *((int8_t*)ap++); + break; + + case nsXPTType::T_I16: + if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t)gprData[iCount++]; + else + dp->val.i16 = *((int16_t*)ap++); + break; + + case nsXPTType::T_I32: + if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t)gprData[iCount++]; + else + dp->val.i32 = *((int32_t*)ap++); + break; + + case nsXPTType::T_I64: + if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t)gprData[iCount++]; + else + dp->val.i64 = *((int64_t*)ap++); + break; + + case nsXPTType::T_U8: + if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t)gprData[iCount++]; + else + dp->val.u8 = *((uint8_t*)ap++); + break; + + case nsXPTType::T_U16: + if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t)gprData[iCount++]; + else + dp->val.u16 = *((uint16_t*)ap++); + break; + + case nsXPTType::T_U32: + if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t)gprData[iCount++]; + else + dp->val.u32 = *((uint32_t*)ap++); + break; + + case nsXPTType::T_U64: + if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t)gprData[iCount++]; + else + dp->val.u64 = *((uint64_t*)ap++); + break; + + case nsXPTType::T_FLOAT: + if (iCount < PARAM_FPR_COUNT) + dp->val.f = (float)fprData[iCount++]; + else + dp->val.f = *((float*)ap++); + break; + + case nsXPTType::T_DOUBLE: + if (iCount < PARAM_FPR_COUNT) + dp->val.d = (double)fprData[iCount++]; + else + dp->val.d = *((double*)ap++); + break; + + case nsXPTType::T_BOOL: + if (iCount < PARAM_GPR_COUNT) + dp->val.b = (bool)gprData[iCount++]; + else + dp->val.b = *((bool*)ap++); + break; + + case nsXPTType::T_CHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char)gprData[iCount++]; + else + dp->val.c = *((char*)ap++); + break; + + case nsXPTType::T_WCHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t)gprData[iCount++]; + else + dp->val.wc = *((wchar_t*)ap++); + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +__asm__ ( + ".text\n" + ".intel_syntax noprefix\n" /* switch to Intel syntax to look like the MSVC assembly */ + ".globl SharedStub\n" + ".def SharedStub ; .scl 3 ; .type 46 ; .endef \n" + "SharedStub:\n" + "sub rsp, 104\n" + + /* rcx is this pointer. Need backup for optimized build */ + + "mov qword ptr [rsp+88], rcx\n" + + /* + * fist 4 parameters (1st is "this" pointer) are passed in registers. + */ + + /* for floating value */ + + "movsd qword ptr [rsp+64], xmm1\n" + "movsd qword ptr [rsp+72], xmm2\n" + "movsd qword ptr [rsp+80], xmm3\n" + + /* for integer value */ + + "mov qword ptr [rsp+40], rdx\n" + "mov qword ptr [rsp+48], r8\n" + "mov qword ptr [rsp+56], r9\n" + + /* + * Call PrepareAndDispatch function + */ + + /* 5th parameter (floating parameters) of PrepareAndDispatch */ + + "lea r9, qword ptr [rsp+64]\n" + "mov qword ptr [rsp+32], r9\n" + + /* 4th parameter (normal parameters) of PrepareAndDispatch */ + + "lea r9, qword ptr [rsp+40]\n" + + /* 3rd parameter (pointer to args on stack) */ + + "lea r8, qword ptr [rsp+40+104]\n" + + /* 2nd parameter (vtbl_index) */ + + "mov rdx, r11\n" + + /* 1st parameter (this) (rcx) */ + + "call PrepareAndDispatch\n" + + /* restore rcx */ + + "mov rcx, qword ptr [rsp+88]\n" + + /* + * clean up register + */ + + "add rsp, 104+8\n" + + /* set return address */ + + "mov rdx, qword ptr [rsp-8]\n" + + /* simulate __stdcall return */ + + "jmp rdx\n" + + /* back to AT&T syntax */ + ".att_syntax\n" +); + +#define STUB_ENTRY(n) \ +asm(".intel_syntax noprefix\n" /* this is in intel syntax */ \ + ".text\n" \ + ".align 2\n" \ + ".if " #n " < 10\n" \ + ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \ + ".def _ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \ + ".scl 3\n" /* private */ \ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + "_ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n" \ + ".elseif " #n " < 100\n" \ + ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \ + ".def _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \ + ".scl 3\n" /* private */\ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + "_ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n" \ + ".elseif " #n " < 1000\n" \ + ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \ + ".def _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \ + ".scl 3\n" /* private */ \ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + "_ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n" \ + ".else\n" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n" \ + ".endif\n" \ + "mov r11, " #n "\n" \ + "jmp SharedStub\n" \ + ".att_syntax\n" /* back to AT&T syntax */ \ + ""); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + diff --git a/xpcom/reflect/xptcall/moz.build b/xpcom/reflect/xptcall/moz.build new file mode 100644 index 000000000..fee7a3352 --- /dev/null +++ b/xpcom/reflect/xptcall/moz.build @@ -0,0 +1,23 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += ['md'] + +SOURCES += [ + 'xptcall.cpp', +] + +EXPORTS += [ + 'xptcall.h', + 'xptcstubsdecl.inc', + 'xptcstubsdef.inc', +] + +LOCAL_INCLUDES += [ + '/xpcom/reflect/xptinfo', +] + +FINAL_LIBRARY = 'xul' diff --git a/xpcom/reflect/xptcall/porting.html b/xpcom/reflect/xptcall/porting.html new file mode 100644 index 000000000..0073c604e --- /dev/null +++ b/xpcom/reflect/xptcall/porting.html @@ -0,0 +1,216 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<html> +<head> +<title>xptcall Porting Guide</title> +</head> +<body bgcolor = "white"> +<h2><center>xptcall Porting Guide</center></h2> + +<h3>Overview</h3> + +<blockquote> + +<a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a> is a +library that supports both invoking methods on arbitrary xpcom objects and +implementing classes whose objects can impersonate any xpcom interface. It does +this using platform specific assembly language code. This code needs to be +ported to all platforms that want to support xptcall (and thus mozilla). + +</blockquote> + +<h3>The tree</h3> + +<blockquote> +<pre> +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a> + +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a> // exported headers + +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a> // core source + | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md">md</a> // platform specific parts + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/mac">mac</a> // mac ppc + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> // all unix + | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a> // win32 + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test">test</a> // simple tests to get started + \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a> // full tests via api +</pre> + +Porters are free to create subdirectories under the base <code>md</code> +directory for their given platforms and to integrate into the build system as +appropriate for their platform. + +</blockquote> + +<h3>Theory of operation</h3> + +<blockquote> + +There are really two pieces of functionality: <i>invoke</i> and <i>stubs</i>... + +<p> + +The <b><i>invoke</i></b> functionality requires the implementation of the +following on each platform (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h">xptcall/xptcall.h</a>): + +<pre> +XPTC_PUBLIC_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); +</pre> + +Calling code is expected to supply an array of <code>nsXPTCVariant</code> +structs. These are discriminated unions describing the type and value of each +parameter of the target function. The platform specific code then builds a call +frame and invokes the method indicated by the index <code>methodIndex</code> on +the xpcom interface <code>that</code>. + +<p> + +Here are examples of this implementation for +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp">Win32</a> +and +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcinvoke_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>. + +Both of these implementations use the basic strategy of: figure out how much +stack space is needed for the params, make the space in a new frame, copy the +params to that space, invoke the method, cleanup and return. C++ is used where +appropriate, Assembly language is used where necessary. Inline assembly language is used here, +but it is equally valid to use separate assembly language source files. Porters +can decide how best to do this for their platforms. + +<p> + +The <b><i>stubs</i></b> functionality is more complex. The goal here is a class +whose vtbl can look like the vtbl of any arbitrary xpcom interface. Objects of +this class can then be built to impersonate any xpcom object. The base interface +for this is (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h">xptcall/xptcall.h</a>): + +<pre> +class nsXPTCStubBase : public nsISupports +{ +public: + // Include generated vtbl stub declarations. + // These are virtual and *also* implemented by this class.. +#include "xptcstubsdecl.inc" + + // The following methods must be provided by inheritor of this class. + + // return a refcounted pointer to the InterfaceInfo for this object + // NOTE: on some platforms this MUST not fail or we crash! + NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info) = 0; + + // call this method and return result + NS_IMETHOD CallMethod(uint16_t methodIndex, + const nsXPTMethodInfo* info, + nsXPTCMiniVariant* params) = 0; +}; +</pre> + +Code that wishes to make use of this <i>stubs</i> functionality (such as +<a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a class +which inherits from <code>nsXPTCStubBase</code> and implements the +<code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the +platform specific code know how to get interface information and how to dispatch methods +once their parameters have been pulled out of the platform specific calling +frame. + +<p> + +Porters of this functionality implement the platform specific code for the +<i>stub</i> methods that fill the vtbl for this class. The idea here is that the +class has a vtbl full of a large number of generic stubs. All instances of this +class share that vtbl and the same stubs. The stubs forward calls to a platform +specific method that uses the interface information supplied by +the overridden <code>GetInterfaceInfo</code> to extract the parameters and build +an array of platform independent <code>nsXPTCMiniVariant</code> structs which +are in turn passed on to the overridden <code>CallMethod</code>. The +platform dependent code is responsible for doing any cleanup and returning. + +<p> + +The stub methods are declared in <a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdecl.inc">xptcall/xptcstubsdecl.inc</a>. +These are '#included' into the declaration of <code>nsXPTCStubBase</code>. A +similar include file (<a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdef.inc">xptcall/xptcstubsdef.inc</a>) +is expanded using platform specific macros to define the stub functions. These +'.inc' files are checked into cvs. However, they can be regenerated as necessary +(i.e. to change the number of stubs or to change their specific declaration) +using the Perl script <a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/genstubs.pl">xptcall/genstubs.pl</a>. + +<p> + +Here are examples of this implementation for <a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp">Win32</a> +and <a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcstubs_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>. +Both of these examples use inline assembly language. That is just how I +decided to do it. You can do it as you choose. + +<p> + +The Win32 version is somewhat tighter because the __declspec(naked) feature +allows for very small stubs. However, the __stdcall requires the callee to clean +up the stack, so it is imperative that the interface information scheme allow +the code to determine the correct stack pointer fixup for return without fail, +else the process will crash. + +<p> + +I opted to use inline assembler for the gcc Linux x86 port. I ended up with +larger stubs than I would have preferred rather than battle the compiler over +what would happen to the stack before my asm code began running. + +<p> + +I believe that the non-assembly parts of these files can be copied and reused +with minimal (but not zero) platform specific tweaks. Feel free to copy and +paste as necessary. Please remember that safety and reliability are more +important than speed optimizations. This code is primarily used to connect XPCOM +components with JavaScript; function call overhead is a <b>tiny</b> part of the +time involved. + +<p> + +I put together +<a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test">xptcall/md/test +</a> as a place to evolve the basic functionality as a port is coming together. +Not all of the functionality is exercised, but it is a place to get started. +<a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">xptcall/tests +</a> has an api level test for <code>NS_InvokeByIndex</code>, but no tests for +the <i>stubs</i> functionality. Such a test ought to be written, but this has not +yet been done. + +<p> + +A full 'test' at this point requires building the client and running the +XPConnect test called <i>TestXPC</i> in +<a +href="http://lxr.mozilla.org/mozilla/source/js/xpconnect/tests">mozilla/js/xpconnect/tests +</a>. + +<p> + +Getting these ports done is very important. Please let <a +href="mailto:jband@netscape.com">me</a> know if you are interested in doing one. +I'll answer any questions as I get them. + +<p> + +<a +href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html"> +Porting Status +</a> + +</blockquote> + +<hr> +<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer <jband@netscape.com></a><br> +<b>Last modified:</b> 31 May 1999 + +</body> +</html> diff --git a/xpcom/reflect/xptcall/status.html b/xpcom/reflect/xptcall/status.html new file mode 100644 index 000000000..65de20596 --- /dev/null +++ b/xpcom/reflect/xptcall/status.html @@ -0,0 +1,412 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<html> +<head> +<title>xptcall Porting Status</title> +</head> +<body bgcolor = "white"> +<h2><center>xptcall Porting Status</center></h2> + +<h3>What is this?</h3> + +This is a status page for the multiplatform porting of xptcall. +xptcall has a +<a href="http://www.mozilla.org/scriptable/xptcall-faq.html">FAQ</a> +and a +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html">Porting Guide</a>. + +<p> + +This is being maintained by <a href="mailto:jband@netscape.com">John Bandhauer <jband@netscape.com></a>. +Feel free to email me with questions or to volunteer to contribute xptcall code for any platform. + +<p> + +<a href="mailto:shaver@mozilla.org">Mike Shaver <shaver@mozilla.org></a> +is the best contact regarding 'nix (Unix, Linux, Finux, etc.) ports of xptcall. + +<h3>Status</h3> + +<table BORDER="1"> +<TR align="left" BGCOLOR="yellow"> +<TH>Status</TH> +<TH>Platform</TH> +<TH><img src="http://tinderbox.mozilla.org/star.gif">Contributors and <font color="red"><b>?</b></font> Possible Contributors</TH> +<TH>Notes</TH> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Win32 x86</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:jband@netscape.com">John Bandhauer <jband@netscape.com></a> +</TD> +<TD> +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a></TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Linux x86</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:jband@netscape.com">John Bandhauer <jband@netscape.com></a><br> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:drepper@cygnus.com">Ulrich Drepper <drepper@cygnus.com></a> +</TD> +<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>FreeBSD and NetBSD x86</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:toshok@hungry.com">Christoph Toshok <toshok@hungry.com></a>,<BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:jband@netscape.com">John Bandhauer <jband@netscape.com></a></TD> +<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> (same as Linux 86 code)</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>BSD/OS x86</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:bert_driehuis@nl.compuware.com">Bert Driehuis <bert_driehuis@nl.compuware.com></a></TD> +<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> (same as Linux 86 code) +Bert contributed patches that *should* do the right thing for all the unixish-x86 +versions of this code for GCC 2.7 or 2.8 vs. EGCS 1.1. He notes that the vtbl +scheme is different. He is hoping that others will help test the changes using +these two compilers on the various platforms where this same code is used. +<a href="news://news.mozilla.org/372DD257.4248C821%40nl.compuware.com">Bert's details</a> +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Mac PPC</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> + <a href="mailto:rogerl@netscape.com">Roger Lawrence <rogerl@netscape.com></a>,<BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:beard@netscape.com">Patrick Beard <beard@netscape.com></a> +</TD> +<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/mac">mac</a> (passing tests and checked in)</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Solaris Sparc</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:rogerl@netscape.com">Roger Lawrence <rogerl@netscape.com></a>,<BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:mcafee@netscape.com">Chris McAfee <mcafee@netscape.com></a> +</TD> +<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> This is checked in and working.</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Solaris Sparc v9 (64bit)</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:pavlov@netscape.com">Stuart Parmenter <pavlov@netscape.com></a>,<BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:cls@seawood.org">Chris Seawood <cls@seawood.org></a> +</TD> +<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> This is checked in and (pavlov claims!) working.</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>OS/2</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:mjf35@cam.ac.uk">John Fairhurst <mjf35@cam.ac.uk></a></TD> +<TD>I never heard exactly who did what. But mozilla has been working on OS/2 +for a long time now. +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>OpenVMS Alpha</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:colin@theblakes.com">Colin R. Blake <colin@theblakes.com></a></TD> +<TD> +Colin says this is passing all the tests on OpenVMS Alpha! +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>NT Alpha</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:bob@guiduck.com">bob meader <bob@guiduck.com></a></TD> +<TD> +bob writes:<br> +Enclosed is xptcall for alpha/nt target.. +<p> +It is a variation of the IRIS port (only targeted for win32). +<p> +Notice the last 2 files (the change to mozilla\xpcom\build\makefile.win and +mozilla\xpcom\build) are needed because I was unable to figure how to do a +"declspecexport" from the assembler ASAXP ... if some knows how to do that then +those last 2 files won't be needed. +<p> +I have had someone look over this code at bridge.com (the entry point to +compaq/gem compiler team) and this code was given the OK. I consider it "done". +<p> +This code lives in the files where the name includes 'alpha' in the <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a> directory.<BR> +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Linux ARM</TD> +<TD><img alt="Started" title="Started" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:sh990154@mail.uni-greifswald.de">Stefan Hanske<sh990154@mail.uni-greifswald.de></a><BR> +<font color="red"><b>?</b></font> +<a href="mailto:willy@bofh.ai">Matthew Wilcox <willy@bofh.ai></a></TD> +<TD> +Stefan's code is checked in and he says it is working. +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Linux Sparc</TD> +<TD> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:anton@progsoc.uts.edu.au">Anton Blanchard <anton@progsoc.uts.edu.au></a>, +<BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:rogerl@netscape.com">Roger Lawrence <rogerl@netscape.com></a>, +<BR> +<img alt="Maybe" title="Maybe" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:ehle.3@osu.eduehle.3@osu.edu">Brandon Ehle <ehle.3@osu.edu></a> +</TD> +<TD> +Anton contributed patches to Roger's Sparc code. Anton says it works and passes the tests!<b> +(24-Aug-1999) Brandon writes: I've finished testing XPTCALL Sparc Linux on 12 different Sparc machines and it checks out good. +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Linux PPC</TD> +<TD> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:beard@netscape.com">Patrick Beard <beard@netscape.com></a><BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:waterson@netscape.com">Chris Waterson <waterson@netscape.com></a><BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:Franz.Sirl-kernel@lauterbach.com">Franz Sirl <Franz.Sirl-kernel@lauterbach.com></a><BR> +<font color="red"><b>?</b></font> +<a href="mailto:jsproul@condor.fddi.wesleyan.edu">Jason Y. Sproul <jsproul@condor.fddi.wesleyan.edu></a><BR> + <font color="red"><b>?</b></font> + <a href="mailto:darkmane@w-link.net">Sean Chitwood <darkmane@w-link.net></a></TD> +<TD> +waterson said: <b>Mozilla runs on Linux/PPC</b> +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Linux Alpha</TD> +<TD> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:glen.nakamura@usa.net">Glen Nakamura <glen.nakamura@usa.net></a><BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:morrildl@nycap.rr.com">Dan Morril <morrildl@nycap.rr.com></a><BR> +</TD> +<TD> +Glen writes: +<p> +I am attaching a patch which contains my Linux Alpha xptcall code. +It passes TestXPTCInvoke and TestXPC on my machine which runs +kernel 2.2.7, glibc 2.1.1, and egcs 1.1.2. I have not tested it +with older GNU compilers such as gcc 2.8.x. From looking at the +Linux x86 code, I gather that the vtable layout is a little different +for those compilers and the code will need minor modifications +in order to work properly. +<p> +I am not sure how much of the code can be used for OpenVMS Alpha +and/or Digital UNIX. Currently the code is dependent on the g++ +name mangling convention and a few GNU extensions so I'm not sure +how useful it will be for the other systems. Hopefully the +comments in the code are detailed enough to help people attempting +a port. +<p> +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>SunOS x86</TD> +<TD> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:aljones@lbl.gov">Arthur Jones <aljones@lbl.gov></a><BR> +<font color="red"><b>?</b></font> +<a href="mailto:ppokorny@mindspring.com">Philip Pokorny <ppokorny@mindspring.com></a><BR> +</TD> +<TD> +The word I hear is that this is working and done +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>HP-UX</TD> +<TD> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:wang@cup.hp.com">Thomas Wang <wang@cup.hp.com></a><BR> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:mgleeson1@netscape.com">Mike Gleeson <mgleeson1@netscape.com></a> +</TD> +<TD>I hear that this code is checked in and working. Though, there is some +doubt - see bug +#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=17997">17997</a> +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>AIX PPC</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:jdunn@netscape.com">Jim Dunn <jdunn@netscape.com></a></TD> +<TD>Philip K. Warren writes: <BR> + +We have gone through several releases of AIX without any problems. +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Irix</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:jasonh@m7.engr.sgi.com">Jason Heirtzler <jasonh@m7.engr.sgi.com></a><BR> +</TD> +<TD>Jason has declared this done. Jason is no longer working at SGI and will +not be maintaining this code. There is some doubt as to whether or not this is +working for everyone - see bug +#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=10061">10061</a>. +<a href="mailto:shaver@mozilla.org">Mike Shaver <shaver@mozilla.org></a> +is the interim maintainer until someone more suitable can be found. +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>BeOS x86</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:duncan@be.com">Duncan Wilcox <duncan@be.com></a><BR> +</TD> +<TD> +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> (yet another reuse of the Linux 86 code!)<BR> +Duncan says this is all working. He did the code for old cfront style 'this' adjustment for others to use too! +</TD> +</TR> + +<TR> +<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD> +<TD>BeOS PPC</TD> +<TD align="center">-</TD> +<TD align="center">-</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Compaq Tru64 UNIX (Digital UNIX)</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:streeter@zk3.dec.com">Steve Streeter <streeter@zk3.dec.com></a><BR> +</TD> +<TD>Code passes the tests and is checked in.</TD> +</TR> + +<TR> +<TD bgcolor="khaki"><font color="black"><b>Working</b></font></TD> +<TD>Neutrio x86</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:Jerry.Kirk@Nexwarecorp.com">Jerry L. Kirk <Jerry.Kirk@Nexwarecorp.com></a><BR> +</TD> +<TD> +Patches for xptc*_unixish_x86.cpp checked in. Waiting for verification that this is really finished. +</TD> +</TR> + +<TR> +<TD bgcolor="khaki"><font color="black"><b>Investigating</b></font></TD> +<TD>SCO UW7 and OSR5</TD> +<TD> +<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:jkj@sco.com">J. Kean Johnston <jkj@sco.com></a><BR> +<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:evanh@sco.com">Evan Hunt <evanh@sco.com></a><BR> +</TD> +<TD>Recent (Feb-2001) email from jkj@sco.com suggests that work will be occuring soon.</TD> +</TR> + +<TR> +<TD bgcolor="khaki"><font color="black"><b>Works</b></font></TD> +<TD>NetBSD/m68k</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:khym@bga.com">Dave Huang <khym@bga.com></a><BR> +</TD> +<TD> +Dave's changes are in the tree. Waiting for verification that it is really finished.</TD> +</TR> + +<TR> +<TD bgcolor="khaki"><font color="black"><b>Partially Working</b></font></TD> +<TD>NetBSD/arm32</TD> +<TD><img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:mpumford@black-star.demon.co.uk">Mike Pumford <mpumford@black-star.demon.co.uk></a> +</TD> +<TD>Mike writes:<BR> +I have started porting to the platform based on the code for Linux ARM. The +InvokeByIndex code works correctly when used with TestXPTCInvoke. I am +currently working on making TestXPC function correctly. +<P> +I am doing the porting work with egcs-1.1.2 on NetBSD 1.4P (NetBSD-current +snapshot from a couple of days ago). +</TD> +</TR> + +<TR> +<TD bgcolor="green"><font color="white"><b>Done</b></font></TD> +<TD>Linux ia64</TD> +<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +HP<br> +<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif"> +<a href="mailto:drepper@redhat.com">Ulrich Drepper <drepper@redhat.com></a> +</TD> +<TD><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=40950#c15">bug 40950 comment 15</a></TD> +</TR> + + +<TR> +<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD> +<TD>All others!</TD> +<TD align="center">-</TD> +<TD align="center">-</TD> +</TR> + + +</table> + +<p> + +<b>Note:</b> I've used the symbol (<font color="red"><b>?</b></font>) to +indicate people who have expressed an interest in <i>possibly</i> contributing code. +Just because these people are listed here does not mean that they have commited +themselves to do the work. If <b>you</b> would like to contribute then let me +know. Feel free to email these folks and offer to help or find out what's going +on. We're all in this together. + +<p> + +<hr> +<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer <jband@netscape.com></a><br> +<b>Last modified:</b> 3 February 2003 + +</body> +</html> diff --git a/xpcom/reflect/xptcall/xptcall.cpp b/xpcom/reflect/xptcall/xptcall.cpp new file mode 100644 index 000000000..1ea0ac34d --- /dev/null +++ b/xpcom/reflect/xptcall/xptcall.cpp @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* entry point wrappers. */ + +#include "xptcprivate.h" +#include "xptiprivate.h" +#include "mozilla/XPTInterfaceInfoManager.h" +#include "nsPrintfCString.h" + +using namespace mozilla; + +NS_IMETHODIMP +nsXPTCStubBase::QueryInterface(REFNSIID aIID, + void **aInstancePtr) +{ + if (aIID.Equals(mEntry->IID())) { + NS_ADDREF_THIS(); + *aInstancePtr = static_cast<nsISupports*>(this); + return NS_OK; + } + + return mOuter->QueryInterface(aIID, aInstancePtr); +} + +NS_IMETHODIMP_(MozExternalRefCountType) +nsXPTCStubBase::AddRef() +{ + return mOuter->AddRef(); +} + +NS_IMETHODIMP_(MozExternalRefCountType) +nsXPTCStubBase::Release() +{ + return mOuter->Release(); +} + +EXPORT_XPCOM_API(nsresult) +NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter, + nsISomeInterface* *aResult) +{ + if (NS_WARN_IF(!aOuter) || NS_WARN_IF(!aResult)) + return NS_ERROR_INVALID_ARG; + + XPTInterfaceInfoManager *iim = + XPTInterfaceInfoManager::GetSingleton(); + if (NS_WARN_IF(!iim)) + return NS_ERROR_NOT_INITIALIZED; + + xptiInterfaceEntry *iie = iim->GetInterfaceEntryForIID(&aIID); + if (!iie || !iie->EnsureResolved() || iie->GetBuiltinClassFlag()) + return NS_ERROR_FAILURE; + + if (iie->GetHasNotXPCOMFlag()) { +#ifdef DEBUG + nsPrintfCString msg("XPTCall will not implement interface %s because of [notxpcom] members.", iie->GetTheName()); + NS_WARNING(msg.get()); +#endif + return NS_ERROR_FAILURE; + } + + *aResult = new nsXPTCStubBase(aOuter, iie); + return NS_OK; +} + +EXPORT_XPCOM_API(void) +NS_DestroyXPTCallStub(nsISomeInterface* aStub) +{ + nsXPTCStubBase* stub = static_cast<nsXPTCStubBase*>(aStub); + delete(stub); +} + +EXPORT_XPCOM_API(size_t) +NS_SizeOfIncludingThisXPTCallStub(const nsISomeInterface* aStub, + mozilla::MallocSizeOf aMallocSizeOf) +{ + // We could cast aStub to nsXPTCStubBase, but that class doesn't seem to own anything, + // so just measure the size of the object itself. + return aMallocSizeOf(aStub); +} diff --git a/xpcom/reflect/xptcall/xptcall.h b/xpcom/reflect/xptcall/xptcall.h new file mode 100644 index 000000000..1f2367b5d --- /dev/null +++ b/xpcom/reflect/xptcall/xptcall.h @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Public declarations for xptcall. */ + +#ifndef xptcall_h___ +#define xptcall_h___ + +#include "nscore.h" +#include "nsISupports.h" +#include "xpt_struct.h" +#include "xptinfo.h" +#include "js/Value.h" +#include "mozilla/MemoryReporting.h" + +struct nsXPTCMiniVariant +{ +// No ctors or dtors so that we can use arrays of these on the stack +// with no penalty. + union + { + int8_t i8; + int16_t i16; + int32_t i32; + int64_t i64; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + float f; + double d; + bool b; + char c; + char16_t wc; + void* p; + + // Types below here are unknown to the assembly implementations, and + // therefore _must_ be passed with indirect semantics. We put them in + // the union here for type safety, so that we can avoid void* tricks. + JS::Value j; + } val; +}; + +struct nsXPTCVariant : public nsXPTCMiniVariant +{ +// No ctors or dtors so that we can use arrays of these on the stack +// with no penalty. + + // inherits 'val' here + void* ptr; + nsXPTType type; + uint8_t flags; + + enum + { + // + // Bitflag definitions + // + + // Indicates that ptr (above, and distinct from val.p) is the value that + // should be passed on the stack. + // + // In theory, ptr could point anywhere. But in practice it always points + // to &val. So this flag is used to pass 'val' by reference, letting us + // avoid the extra allocation we would incur if we were to use val.p. + // + // Various parts of XPConnect assume that ptr==&val, so we enforce it + // explicitly with SetIndirect() and IsIndirect(). + // + // Since ptr always points to &val, the semantics of this flag are kind of + // dumb, since the ptr field is unnecessary. But changing them would + // require changing dozens of assembly files, so they're likely to stay + // the way they are. + PTR_IS_DATA = 0x1, + + // Indicates that the value we hold requires some sort of cleanup (memory + // deallocation, interface release, JS::Value unrooting, etc). The precise + // cleanup that is performed depends on the 'type' field above. + // If the value is an array, this flag specifies whether the elements + // within the array require cleanup (we always clean up the array itself, + // so this flag would be redundant for that purpose). + VAL_NEEDS_CLEANUP = 0x2 + }; + + void ClearFlags() {flags = 0;} + void SetIndirect() {ptr = &val; flags |= PTR_IS_DATA;} + void SetValNeedsCleanup() {flags |= VAL_NEEDS_CLEANUP;} + + bool IsIndirect() const {return 0 != (flags & PTR_IS_DATA);} + bool DoesValNeedCleanup() const {return 0 != (flags & VAL_NEEDS_CLEANUP);} + + // Internal use only. Use IsIndirect() instead. + bool IsPtrData() const {return 0 != (flags & PTR_IS_DATA);} + + void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, uint8_t f) + { + type = t; + flags = f; + + if(f & PTR_IS_DATA) + { + ptr = mv.val.p; + val.p = nullptr; + } + else + { + ptr = nullptr; + val.p = nullptr; // make sure 'val.p' is always initialized + switch(t.TagPart()) { + case nsXPTType::T_I8: val.i8 = mv.val.i8; break; + case nsXPTType::T_I16: val.i16 = mv.val.i16; break; + case nsXPTType::T_I32: val.i32 = mv.val.i32; break; + case nsXPTType::T_I64: val.i64 = mv.val.i64; break; + case nsXPTType::T_U8: val.u8 = mv.val.u8; break; + case nsXPTType::T_U16: val.u16 = mv.val.u16; break; + case nsXPTType::T_U32: val.u32 = mv.val.u32; break; + case nsXPTType::T_U64: val.u64 = mv.val.u64; break; + case nsXPTType::T_FLOAT: val.f = mv.val.f; break; + case nsXPTType::T_DOUBLE: val.d = mv.val.d; break; + case nsXPTType::T_BOOL: val.b = mv.val.b; break; + case nsXPTType::T_CHAR: val.c = mv.val.c; break; + case nsXPTType::T_WCHAR: val.wc = mv.val.wc; break; + case nsXPTType::T_VOID: /* fall through */ + case nsXPTType::T_IID: /* fall through */ + case nsXPTType::T_DOMSTRING: /* fall through */ + case nsXPTType::T_CHAR_STR: /* fall through */ + case nsXPTType::T_WCHAR_STR: /* fall through */ + case nsXPTType::T_INTERFACE: /* fall through */ + case nsXPTType::T_INTERFACE_IS: /* fall through */ + case nsXPTType::T_ARRAY: /* fall through */ + case nsXPTType::T_PSTRING_SIZE_IS: /* fall through */ + case nsXPTType::T_PWSTRING_SIZE_IS: /* fall through */ + case nsXPTType::T_UTF8STRING: /* fall through */ + case nsXPTType::T_CSTRING: /* fall through */ + default: val.p = mv.val.p; break; + } + } + } +}; + +class nsIXPTCProxy : public nsISupports +{ +public: + NS_IMETHOD CallMethod(uint16_t aMethodIndex, + const XPTMethodDescriptor *aInfo, + nsXPTCMiniVariant *aParams) = 0; +}; + +/** + * This is a typedef to avoid confusion between the canonical + * nsISupports* that provides object identity and an interface pointer + * for inheriting interfaces that aren't known at compile-time. + */ +typedef nsISupports nsISomeInterface; + +/** + * Get a proxy object to implement the specified interface. + * + * @param aIID The IID of the interface to implement. + * @param aOuter An object to receive method calls from the proxy object. + * The stub forwards QueryInterface/AddRef/Release to the + * outer object. The proxy object does not hold a reference to + * the outer object; it is the caller's responsibility to + * ensure that this pointer remains valid until the stub has + * been destroyed. + * @param aStub Out parameter for the new proxy object. The object is + * not addrefed. The object never destroys itself. It must be + * explicitly destroyed by calling + * NS_DestroyXPTCallStub when it is no longer needed. + */ +XPCOM_API(nsresult) +NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter, + nsISomeInterface* *aStub); + +/** + * Destroys an XPTCall stub previously created with NS_GetXPTCallStub. + */ +XPCOM_API(void) +NS_DestroyXPTCallStub(nsISomeInterface* aStub); + +/** + * Measures the size of an XPTCall stub previously created with NS_GetXPTCallStub. + */ +XPCOM_API(size_t) +NS_SizeOfIncludingThisXPTCallStub(const nsISomeInterface* aStub, mozilla::MallocSizeOf aMallocSizeOf); + +XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +#endif /* xptcall_h___ */ diff --git a/xpcom/reflect/xptcall/xptcprivate.h b/xpcom/reflect/xptcall/xptcprivate.h new file mode 100644 index 000000000..7805792e7 --- /dev/null +++ b/xpcom/reflect/xptcall/xptcprivate.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* All the xptcall private declarations - only include locally. */ + +#ifndef xptcprivate_h___ +#define xptcprivate_h___ + +#include "xptcall.h" +#include "nsAutoPtr.h" +#include "mozilla/Attributes.h" + +class xptiInterfaceEntry; + +#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) +#define STUB_ENTRY(n) NS_IMETHOD Stub##n() = 0; +#else +#define STUB_ENTRY(n) NS_IMETHOD Stub##n(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t) = 0; +#endif + +#define SENTINEL_ENTRY(n) NS_IMETHOD Sentinel##n() = 0; + +class nsIXPTCStubBase : public nsISupports +{ +public: +#include "xptcstubsdef.inc" +}; + +#undef STUB_ENTRY +#undef SENTINEL_ENTRY + +#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) +#define STUB_ENTRY(n) NS_IMETHOD Stub##n() override; +#else +#define STUB_ENTRY(n) NS_IMETHOD Stub##n(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t) override; +#endif + +#define SENTINEL_ENTRY(n) NS_IMETHOD Sentinel##n() override; + +class nsXPTCStubBase final : public nsIXPTCStubBase +{ +public: + NS_DECL_ISUPPORTS_INHERITED + +#include "xptcstubsdef.inc" + + nsXPTCStubBase(nsIXPTCProxy* aOuter, xptiInterfaceEntry *aEntry) + : mOuter(aOuter), mEntry(aEntry) { MOZ_COUNT_CTOR(nsXPTCStubBase); } + + nsIXPTCProxy* mOuter; + xptiInterfaceEntry* mEntry; + + ~nsXPTCStubBase() { MOZ_COUNT_DTOR(nsXPTCStubBase); } +}; + +#undef STUB_ENTRY +#undef SENTINEL_ENTRY + +#if defined(__clang__) || defined(__GNUC__) +#define ATTRIBUTE_USED __attribute__ ((__used__)) +#else +#define ATTRIBUTE_USED +#endif + +#endif /* xptcprivate_h___ */ diff --git a/xpcom/reflect/xptcall/xptcstubsdecl.inc b/xpcom/reflect/xptcall/xptcstubsdecl.inc new file mode 100644 index 000000000..91d35fe32 --- /dev/null +++ b/xpcom/reflect/xptcall/xptcstubsdecl.inc @@ -0,0 +1,761 @@ +/* generated file - DO NOT EDIT */ + +/* includes 247 stub entries, and 5 sentinel entries */ + +/* +* declarations of normal stubs... +* 0 is QueryInterface +* 1 is AddRef +* 2 is Release +*/ +#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) +NS_IMETHOD Stub3(); +NS_IMETHOD Stub4(); +NS_IMETHOD Stub5(); +NS_IMETHOD Stub6(); +NS_IMETHOD Stub7(); +NS_IMETHOD Stub8(); +NS_IMETHOD Stub9(); +NS_IMETHOD Stub10(); +NS_IMETHOD Stub11(); +NS_IMETHOD Stub12(); +NS_IMETHOD Stub13(); +NS_IMETHOD Stub14(); +NS_IMETHOD Stub15(); +NS_IMETHOD Stub16(); +NS_IMETHOD Stub17(); +NS_IMETHOD Stub18(); +NS_IMETHOD Stub19(); +NS_IMETHOD Stub20(); +NS_IMETHOD Stub21(); +NS_IMETHOD Stub22(); +NS_IMETHOD Stub23(); +NS_IMETHOD Stub24(); +NS_IMETHOD Stub25(); +NS_IMETHOD Stub26(); +NS_IMETHOD Stub27(); +NS_IMETHOD Stub28(); +NS_IMETHOD Stub29(); +NS_IMETHOD Stub30(); +NS_IMETHOD Stub31(); +NS_IMETHOD Stub32(); +NS_IMETHOD Stub33(); +NS_IMETHOD Stub34(); +NS_IMETHOD Stub35(); +NS_IMETHOD Stub36(); +NS_IMETHOD Stub37(); +NS_IMETHOD Stub38(); +NS_IMETHOD Stub39(); +NS_IMETHOD Stub40(); +NS_IMETHOD Stub41(); +NS_IMETHOD Stub42(); +NS_IMETHOD Stub43(); +NS_IMETHOD Stub44(); +NS_IMETHOD Stub45(); +NS_IMETHOD Stub46(); +NS_IMETHOD Stub47(); +NS_IMETHOD Stub48(); +NS_IMETHOD Stub49(); +NS_IMETHOD Stub50(); +NS_IMETHOD Stub51(); +NS_IMETHOD Stub52(); +NS_IMETHOD Stub53(); +NS_IMETHOD Stub54(); +NS_IMETHOD Stub55(); +NS_IMETHOD Stub56(); +NS_IMETHOD Stub57(); +NS_IMETHOD Stub58(); +NS_IMETHOD Stub59(); +NS_IMETHOD Stub60(); +NS_IMETHOD Stub61(); +NS_IMETHOD Stub62(); +NS_IMETHOD Stub63(); +NS_IMETHOD Stub64(); +NS_IMETHOD Stub65(); +NS_IMETHOD Stub66(); +NS_IMETHOD Stub67(); +NS_IMETHOD Stub68(); +NS_IMETHOD Stub69(); +NS_IMETHOD Stub70(); +NS_IMETHOD Stub71(); +NS_IMETHOD Stub72(); +NS_IMETHOD Stub73(); +NS_IMETHOD Stub74(); +NS_IMETHOD Stub75(); +NS_IMETHOD Stub76(); +NS_IMETHOD Stub77(); +NS_IMETHOD Stub78(); +NS_IMETHOD Stub79(); +NS_IMETHOD Stub80(); +NS_IMETHOD Stub81(); +NS_IMETHOD Stub82(); +NS_IMETHOD Stub83(); +NS_IMETHOD Stub84(); +NS_IMETHOD Stub85(); +NS_IMETHOD Stub86(); +NS_IMETHOD Stub87(); +NS_IMETHOD Stub88(); +NS_IMETHOD Stub89(); +NS_IMETHOD Stub90(); +NS_IMETHOD Stub91(); +NS_IMETHOD Stub92(); +NS_IMETHOD Stub93(); +NS_IMETHOD Stub94(); +NS_IMETHOD Stub95(); +NS_IMETHOD Stub96(); +NS_IMETHOD Stub97(); +NS_IMETHOD Stub98(); +NS_IMETHOD Stub99(); +NS_IMETHOD Stub100(); +NS_IMETHOD Stub101(); +NS_IMETHOD Stub102(); +NS_IMETHOD Stub103(); +NS_IMETHOD Stub104(); +NS_IMETHOD Stub105(); +NS_IMETHOD Stub106(); +NS_IMETHOD Stub107(); +NS_IMETHOD Stub108(); +NS_IMETHOD Stub109(); +NS_IMETHOD Stub110(); +NS_IMETHOD Stub111(); +NS_IMETHOD Stub112(); +NS_IMETHOD Stub113(); +NS_IMETHOD Stub114(); +NS_IMETHOD Stub115(); +NS_IMETHOD Stub116(); +NS_IMETHOD Stub117(); +NS_IMETHOD Stub118(); +NS_IMETHOD Stub119(); +NS_IMETHOD Stub120(); +NS_IMETHOD Stub121(); +NS_IMETHOD Stub122(); +NS_IMETHOD Stub123(); +NS_IMETHOD Stub124(); +NS_IMETHOD Stub125(); +NS_IMETHOD Stub126(); +NS_IMETHOD Stub127(); +NS_IMETHOD Stub128(); +NS_IMETHOD Stub129(); +NS_IMETHOD Stub130(); +NS_IMETHOD Stub131(); +NS_IMETHOD Stub132(); +NS_IMETHOD Stub133(); +NS_IMETHOD Stub134(); +NS_IMETHOD Stub135(); +NS_IMETHOD Stub136(); +NS_IMETHOD Stub137(); +NS_IMETHOD Stub138(); +NS_IMETHOD Stub139(); +NS_IMETHOD Stub140(); +NS_IMETHOD Stub141(); +NS_IMETHOD Stub142(); +NS_IMETHOD Stub143(); +NS_IMETHOD Stub144(); +NS_IMETHOD Stub145(); +NS_IMETHOD Stub146(); +NS_IMETHOD Stub147(); +NS_IMETHOD Stub148(); +NS_IMETHOD Stub149(); +NS_IMETHOD Stub150(); +NS_IMETHOD Stub151(); +NS_IMETHOD Stub152(); +NS_IMETHOD Stub153(); +NS_IMETHOD Stub154(); +NS_IMETHOD Stub155(); +NS_IMETHOD Stub156(); +NS_IMETHOD Stub157(); +NS_IMETHOD Stub158(); +NS_IMETHOD Stub159(); +NS_IMETHOD Stub160(); +NS_IMETHOD Stub161(); +NS_IMETHOD Stub162(); +NS_IMETHOD Stub163(); +NS_IMETHOD Stub164(); +NS_IMETHOD Stub165(); +NS_IMETHOD Stub166(); +NS_IMETHOD Stub167(); +NS_IMETHOD Stub168(); +NS_IMETHOD Stub169(); +NS_IMETHOD Stub170(); +NS_IMETHOD Stub171(); +NS_IMETHOD Stub172(); +NS_IMETHOD Stub173(); +NS_IMETHOD Stub174(); +NS_IMETHOD Stub175(); +NS_IMETHOD Stub176(); +NS_IMETHOD Stub177(); +NS_IMETHOD Stub178(); +NS_IMETHOD Stub179(); +NS_IMETHOD Stub180(); +NS_IMETHOD Stub181(); +NS_IMETHOD Stub182(); +NS_IMETHOD Stub183(); +NS_IMETHOD Stub184(); +NS_IMETHOD Stub185(); +NS_IMETHOD Stub186(); +NS_IMETHOD Stub187(); +NS_IMETHOD Stub188(); +NS_IMETHOD Stub189(); +NS_IMETHOD Stub190(); +NS_IMETHOD Stub191(); +NS_IMETHOD Stub192(); +NS_IMETHOD Stub193(); +NS_IMETHOD Stub194(); +NS_IMETHOD Stub195(); +NS_IMETHOD Stub196(); +NS_IMETHOD Stub197(); +NS_IMETHOD Stub198(); +NS_IMETHOD Stub199(); +NS_IMETHOD Stub200(); +NS_IMETHOD Stub201(); +NS_IMETHOD Stub202(); +NS_IMETHOD Stub203(); +NS_IMETHOD Stub204(); +NS_IMETHOD Stub205(); +NS_IMETHOD Stub206(); +NS_IMETHOD Stub207(); +NS_IMETHOD Stub208(); +NS_IMETHOD Stub209(); +NS_IMETHOD Stub210(); +NS_IMETHOD Stub211(); +NS_IMETHOD Stub212(); +NS_IMETHOD Stub213(); +NS_IMETHOD Stub214(); +NS_IMETHOD Stub215(); +NS_IMETHOD Stub216(); +NS_IMETHOD Stub217(); +NS_IMETHOD Stub218(); +NS_IMETHOD Stub219(); +NS_IMETHOD Stub220(); +NS_IMETHOD Stub221(); +NS_IMETHOD Stub222(); +NS_IMETHOD Stub223(); +NS_IMETHOD Stub224(); +NS_IMETHOD Stub225(); +NS_IMETHOD Stub226(); +NS_IMETHOD Stub227(); +NS_IMETHOD Stub228(); +NS_IMETHOD Stub229(); +NS_IMETHOD Stub230(); +NS_IMETHOD Stub231(); +NS_IMETHOD Stub232(); +NS_IMETHOD Stub233(); +NS_IMETHOD Stub234(); +NS_IMETHOD Stub235(); +NS_IMETHOD Stub236(); +NS_IMETHOD Stub237(); +NS_IMETHOD Stub238(); +NS_IMETHOD Stub239(); +NS_IMETHOD Stub240(); +NS_IMETHOD Stub241(); +NS_IMETHOD Stub242(); +NS_IMETHOD Stub243(); +NS_IMETHOD Stub244(); +NS_IMETHOD Stub245(); +NS_IMETHOD Stub246(); +NS_IMETHOD Stub247(); +NS_IMETHOD Stub248(); +NS_IMETHOD Stub249(); +#else +NS_IMETHOD Stub3(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub4(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub5(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub6(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub7(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub8(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub9(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub10(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub11(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub12(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub13(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub14(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub15(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub16(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub17(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub18(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub19(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub20(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub21(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub22(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub23(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub24(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub25(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub26(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub27(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub28(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub29(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub30(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub31(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub32(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub33(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub34(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub35(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub36(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub37(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub38(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub39(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub40(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub41(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub42(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub43(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub44(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub45(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub46(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub47(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub48(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub49(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub50(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub51(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub52(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub53(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub54(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub55(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub56(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub57(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub58(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub59(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub60(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub61(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub62(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub63(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub64(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub65(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub66(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub67(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub68(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub69(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub70(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub71(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub72(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub73(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub74(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub75(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub76(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub77(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub78(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub79(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub80(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub81(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub82(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub83(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub84(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub85(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub86(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub87(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub88(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub89(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub90(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub91(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub92(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub93(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub94(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub95(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub96(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub97(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub98(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub99(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub100(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub101(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub102(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub103(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub104(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub105(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub106(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub107(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub108(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub109(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub110(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub111(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub112(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub113(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub114(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub115(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub116(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub117(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub118(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub119(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub120(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub121(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub122(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub123(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub124(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub125(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub126(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub127(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub128(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub129(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub130(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub131(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub132(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub133(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub134(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub135(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub136(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub137(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub138(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub139(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub140(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub141(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub142(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub143(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub144(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub145(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub146(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub147(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub148(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub149(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub150(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub151(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub152(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub153(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub154(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub155(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub156(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub157(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub158(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub159(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub160(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub161(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub162(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub163(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub164(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub165(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub166(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub167(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub168(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub169(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub170(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub171(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub172(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub173(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub174(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub175(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub176(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub177(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub178(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub179(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub180(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub181(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub182(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub183(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub184(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub185(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub186(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub187(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub188(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub189(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub190(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub191(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub192(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub193(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub194(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub195(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub196(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub197(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub198(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub199(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub200(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub201(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub202(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub203(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub204(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub205(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub206(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub207(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub208(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub209(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub210(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub211(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub212(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub213(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub214(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub215(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub216(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub217(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub218(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub219(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub220(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub221(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub222(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub223(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub224(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub225(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub226(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub227(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub228(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub229(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub230(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub231(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub232(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub233(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub234(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub235(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub236(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub237(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub238(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub239(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub240(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub241(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub242(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub243(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub244(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub245(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub246(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub247(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub248(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub249(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +#endif + +/* declarations of sentinel stubs */ +NS_IMETHOD Sentinel0(); +NS_IMETHOD Sentinel1(); +NS_IMETHOD Sentinel2(); +NS_IMETHOD Sentinel3(); +NS_IMETHOD Sentinel4(); diff --git a/xpcom/reflect/xptcall/xptcstubsdef.inc b/xpcom/reflect/xptcall/xptcstubsdef.inc new file mode 100644 index 000000000..2df455406 --- /dev/null +++ b/xpcom/reflect/xptcall/xptcstubsdef.inc @@ -0,0 +1,252 @@ +STUB_ENTRY(3) +STUB_ENTRY(4) +STUB_ENTRY(5) +STUB_ENTRY(6) +STUB_ENTRY(7) +STUB_ENTRY(8) +STUB_ENTRY(9) +STUB_ENTRY(10) +STUB_ENTRY(11) +STUB_ENTRY(12) +STUB_ENTRY(13) +STUB_ENTRY(14) +STUB_ENTRY(15) +STUB_ENTRY(16) +STUB_ENTRY(17) +STUB_ENTRY(18) +STUB_ENTRY(19) +STUB_ENTRY(20) +STUB_ENTRY(21) +STUB_ENTRY(22) +STUB_ENTRY(23) +STUB_ENTRY(24) +STUB_ENTRY(25) +STUB_ENTRY(26) +STUB_ENTRY(27) +STUB_ENTRY(28) +STUB_ENTRY(29) +STUB_ENTRY(30) +STUB_ENTRY(31) +STUB_ENTRY(32) +STUB_ENTRY(33) +STUB_ENTRY(34) +STUB_ENTRY(35) +STUB_ENTRY(36) +STUB_ENTRY(37) +STUB_ENTRY(38) +STUB_ENTRY(39) +STUB_ENTRY(40) +STUB_ENTRY(41) +STUB_ENTRY(42) +STUB_ENTRY(43) +STUB_ENTRY(44) +STUB_ENTRY(45) +STUB_ENTRY(46) +STUB_ENTRY(47) +STUB_ENTRY(48) +STUB_ENTRY(49) +STUB_ENTRY(50) +STUB_ENTRY(51) +STUB_ENTRY(52) +STUB_ENTRY(53) +STUB_ENTRY(54) +STUB_ENTRY(55) +STUB_ENTRY(56) +STUB_ENTRY(57) +STUB_ENTRY(58) +STUB_ENTRY(59) +STUB_ENTRY(60) +STUB_ENTRY(61) +STUB_ENTRY(62) +STUB_ENTRY(63) +STUB_ENTRY(64) +STUB_ENTRY(65) +STUB_ENTRY(66) +STUB_ENTRY(67) +STUB_ENTRY(68) +STUB_ENTRY(69) +STUB_ENTRY(70) +STUB_ENTRY(71) +STUB_ENTRY(72) +STUB_ENTRY(73) +STUB_ENTRY(74) +STUB_ENTRY(75) +STUB_ENTRY(76) +STUB_ENTRY(77) +STUB_ENTRY(78) +STUB_ENTRY(79) +STUB_ENTRY(80) +STUB_ENTRY(81) +STUB_ENTRY(82) +STUB_ENTRY(83) +STUB_ENTRY(84) +STUB_ENTRY(85) +STUB_ENTRY(86) +STUB_ENTRY(87) +STUB_ENTRY(88) +STUB_ENTRY(89) +STUB_ENTRY(90) +STUB_ENTRY(91) +STUB_ENTRY(92) +STUB_ENTRY(93) +STUB_ENTRY(94) +STUB_ENTRY(95) +STUB_ENTRY(96) +STUB_ENTRY(97) +STUB_ENTRY(98) +STUB_ENTRY(99) +STUB_ENTRY(100) +STUB_ENTRY(101) +STUB_ENTRY(102) +STUB_ENTRY(103) +STUB_ENTRY(104) +STUB_ENTRY(105) +STUB_ENTRY(106) +STUB_ENTRY(107) +STUB_ENTRY(108) +STUB_ENTRY(109) +STUB_ENTRY(110) +STUB_ENTRY(111) +STUB_ENTRY(112) +STUB_ENTRY(113) +STUB_ENTRY(114) +STUB_ENTRY(115) +STUB_ENTRY(116) +STUB_ENTRY(117) +STUB_ENTRY(118) +STUB_ENTRY(119) +STUB_ENTRY(120) +STUB_ENTRY(121) +STUB_ENTRY(122) +STUB_ENTRY(123) +STUB_ENTRY(124) +STUB_ENTRY(125) +STUB_ENTRY(126) +STUB_ENTRY(127) +STUB_ENTRY(128) +STUB_ENTRY(129) +STUB_ENTRY(130) +STUB_ENTRY(131) +STUB_ENTRY(132) +STUB_ENTRY(133) +STUB_ENTRY(134) +STUB_ENTRY(135) +STUB_ENTRY(136) +STUB_ENTRY(137) +STUB_ENTRY(138) +STUB_ENTRY(139) +STUB_ENTRY(140) +STUB_ENTRY(141) +STUB_ENTRY(142) +STUB_ENTRY(143) +STUB_ENTRY(144) +STUB_ENTRY(145) +STUB_ENTRY(146) +STUB_ENTRY(147) +STUB_ENTRY(148) +STUB_ENTRY(149) +STUB_ENTRY(150) +STUB_ENTRY(151) +STUB_ENTRY(152) +STUB_ENTRY(153) +STUB_ENTRY(154) +STUB_ENTRY(155) +STUB_ENTRY(156) +STUB_ENTRY(157) +STUB_ENTRY(158) +STUB_ENTRY(159) +STUB_ENTRY(160) +STUB_ENTRY(161) +STUB_ENTRY(162) +STUB_ENTRY(163) +STUB_ENTRY(164) +STUB_ENTRY(165) +STUB_ENTRY(166) +STUB_ENTRY(167) +STUB_ENTRY(168) +STUB_ENTRY(169) +STUB_ENTRY(170) +STUB_ENTRY(171) +STUB_ENTRY(172) +STUB_ENTRY(173) +STUB_ENTRY(174) +STUB_ENTRY(175) +STUB_ENTRY(176) +STUB_ENTRY(177) +STUB_ENTRY(178) +STUB_ENTRY(179) +STUB_ENTRY(180) +STUB_ENTRY(181) +STUB_ENTRY(182) +STUB_ENTRY(183) +STUB_ENTRY(184) +STUB_ENTRY(185) +STUB_ENTRY(186) +STUB_ENTRY(187) +STUB_ENTRY(188) +STUB_ENTRY(189) +STUB_ENTRY(190) +STUB_ENTRY(191) +STUB_ENTRY(192) +STUB_ENTRY(193) +STUB_ENTRY(194) +STUB_ENTRY(195) +STUB_ENTRY(196) +STUB_ENTRY(197) +STUB_ENTRY(198) +STUB_ENTRY(199) +STUB_ENTRY(200) +STUB_ENTRY(201) +STUB_ENTRY(202) +STUB_ENTRY(203) +STUB_ENTRY(204) +STUB_ENTRY(205) +STUB_ENTRY(206) +STUB_ENTRY(207) +STUB_ENTRY(208) +STUB_ENTRY(209) +STUB_ENTRY(210) +STUB_ENTRY(211) +STUB_ENTRY(212) +STUB_ENTRY(213) +STUB_ENTRY(214) +STUB_ENTRY(215) +STUB_ENTRY(216) +STUB_ENTRY(217) +STUB_ENTRY(218) +STUB_ENTRY(219) +STUB_ENTRY(220) +STUB_ENTRY(221) +STUB_ENTRY(222) +STUB_ENTRY(223) +STUB_ENTRY(224) +STUB_ENTRY(225) +STUB_ENTRY(226) +STUB_ENTRY(227) +STUB_ENTRY(228) +STUB_ENTRY(229) +STUB_ENTRY(230) +STUB_ENTRY(231) +STUB_ENTRY(232) +STUB_ENTRY(233) +STUB_ENTRY(234) +STUB_ENTRY(235) +STUB_ENTRY(236) +STUB_ENTRY(237) +STUB_ENTRY(238) +STUB_ENTRY(239) +STUB_ENTRY(240) +STUB_ENTRY(241) +STUB_ENTRY(242) +STUB_ENTRY(243) +STUB_ENTRY(244) +STUB_ENTRY(245) +STUB_ENTRY(246) +STUB_ENTRY(247) +STUB_ENTRY(248) +STUB_ENTRY(249) +SENTINEL_ENTRY(0) +SENTINEL_ENTRY(1) +SENTINEL_ENTRY(2) +SENTINEL_ENTRY(3) +SENTINEL_ENTRY(4) diff --git a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp new file mode 100644 index 000000000..14e719f6c --- /dev/null +++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp @@ -0,0 +1,700 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sw=4 et tw=78: + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ShimInterfaceInfo.h" + +#include "nsIBrowserBoxObject.h" +#include "nsIContainerBoxObject.h" +#include "nsIDOMAnimationEvent.h" +#include "nsIDOMAttr.h" +#include "nsIDOMBeforeUnloadEvent.h" +#include "nsIDOMCanvasRenderingContext2D.h" +#include "nsIDOMCDATASection.h" +#include "nsIDOMCharacterData.h" +#include "nsIDOMClientRect.h" +#include "nsIDOMClientRectList.h" +#include "nsIDOMClipboardEvent.h" +#include "nsIDOMCommandEvent.h" +#include "nsIDOMComment.h" +#include "nsIDOMCSSPrimitiveValue.h" +#include "nsIDOMCSSStyleDeclaration.h" +#include "nsIDOMCSSStyleSheet.h" +#include "nsIDOMCSSValue.h" +#include "nsIDOMCSSValueList.h" +#include "nsIDOMCustomEvent.h" +#include "nsIDOMDataContainerEvent.h" +#ifdef MOZ_WEBRTC +#include "nsIDOMDataChannel.h" +#endif +#include "nsIDOMDataTransfer.h" +#include "nsIDOMDOMCursor.h" +#include "nsIDOMDOMException.h" +#include "nsIDOMDOMRequest.h" +#include "nsIDOMDocument.h" +#include "nsIDOMDocumentFragment.h" +#include "nsIDOMDocumentType.h" +#include "nsIDOMDocumentXBL.h" +#include "nsIDOMDragEvent.h" +#include "nsIDOMElement.h" +#include "nsIDOMEvent.h" +#include "nsIDOMEventTarget.h" +#include "nsIDOMFileList.h" +#include "nsIDOMFocusEvent.h" +#include "nsIDOMFormData.h" +#include "nsIDOMGeoPositionError.h" +#include "nsIDOMHistory.h" +#include "nsIDOMHTMLAnchorElement.h" +#include "nsIDOMHTMLAppletElement.h" +#include "nsIDOMHTMLAreaElement.h" +#include "nsIDOMHTMLBaseElement.h" +#include "nsIDOMHTMLBodyElement.h" +#include "nsIDOMHTMLButtonElement.h" +#include "nsIDOMHTMLCanvasElement.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIDOMHTMLDirectoryElement.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIDOMHTMLElement.h" +#include "nsIDOMHTMLEmbedElement.h" +#include "nsIDOMHTMLFieldSetElement.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIDOMHTMLFrameElement.h" +#include "nsIDOMHTMLFrameSetElement.h" +#include "nsIDOMHTMLHRElement.h" +#include "nsIDOMHTMLHeadElement.h" +#include "nsIDOMHTMLHtmlElement.h" +#include "nsIDOMHTMLIFrameElement.h" +#include "nsIDOMHTMLImageElement.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLLIElement.h" +#include "nsIDOMHTMLLabelElement.h" +#include "nsIDOMHTMLLinkElement.h" +#include "nsIDOMHTMLMapElement.h" +#include "nsIDOMHTMLMediaElement.h" +#include "nsIDOMHTMLMenuElement.h" +#include "nsIDOMHTMLMenuItemElement.h" +#include "nsIDOMHTMLMetaElement.h" +#include "nsIDOMHTMLOListElement.h" +#include "nsIDOMHTMLObjectElement.h" +#include "nsIDOMHTMLOptGroupElement.h" +#include "nsIDOMHTMLOptionElement.h" +#include "nsIDOMHTMLOptionsCollection.h" +#include "nsIDOMHTMLParagraphElement.h" +#include "nsIDOMHTMLPreElement.h" +#include "nsIDOMHTMLQuoteElement.h" +#include "nsIDOMHTMLScriptElement.h" +#include "nsIDOMHTMLSelectElement.h" +#include "nsIDOMHTMLSourceElement.h" +#include "nsIDOMHTMLStyleElement.h" +#include "nsIDOMHTMLTableCellElement.h" +#include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLUListElement.h" +#include "nsIDOMKeyEvent.h" +#include "nsIDOMMediaList.h" +#include "nsIDOMMouseEvent.h" +#include "nsIDOMMouseScrollEvent.h" +#include "nsIDOMMutationEvent.h" +#include "nsIDOMMozNamedAttrMap.h" +#include "nsIDOMNode.h" +#include "nsIDOMNodeIterator.h" +#include "nsIDOMNotifyPaintEvent.h" +#include "nsIDOMNSEvent.h" +#include "nsIDOMOfflineResourceList.h" +#include "nsIDOMPaintRequest.h" +#include "nsIDOMParser.h" +#include "nsIDOMProcessingInstruction.h" +#include "nsIDOMRange.h" +#include "nsIDOMRect.h" +#include "nsIDOMScreen.h" +#include "nsIDOMScrollAreaEvent.h" +#include "nsIDOMSerializer.h" +#include "nsIDOMSimpleGestureEvent.h" +#include "nsIDOMStyleSheet.h" +#include "nsIDOMStyleSheetList.h" +#include "nsIDOMSVGElement.h" +#include "nsIDOMSVGLength.h" +#include "nsIDOMText.h" +#include "nsIDOMTimeEvent.h" +#include "nsIDOMTimeRanges.h" +#include "nsIDOMTransitionEvent.h" +#include "nsIDOMTreeWalker.h" +#include "nsIDOMUIEvent.h" +#include "nsIDOMValidityState.h" +#include "nsIDOMWheelEvent.h" +#include "nsIDOMXMLDocument.h" +#include "nsIDOMXPathEvaluator.h" +#include "nsIDOMXPathResult.h" +#include "nsIDOMXULCommandEvent.h" +#include "nsIDOMXULDocument.h" +#include "nsIDOMXULElement.h" +#include "nsIListBoxObject.h" +#include "nsIMenuBoxObject.h" +#include "nsIScrollBoxObject.h" +#include "nsISelection.h" +#include "nsITreeBoxObject.h" +#include "nsIXMLHttpRequest.h" + +#include "mozilla/dom/AnimationEventBinding.h" +#include "mozilla/dom/AttrBinding.h" +#include "mozilla/dom/BeforeUnloadEventBinding.h" +#include "mozilla/dom/CanvasRenderingContext2DBinding.h" +#include "mozilla/dom/CDATASectionBinding.h" +#include "mozilla/dom/CharacterDataBinding.h" +#include "mozilla/dom/DOMRectBinding.h" +#include "mozilla/dom/DOMRectListBinding.h" +#include "mozilla/dom/ClipboardEventBinding.h" +#include "mozilla/dom/CommandEventBinding.h" +#include "mozilla/dom/CommentBinding.h" +#include "mozilla/dom/ContainerBoxObjectBinding.h" +#include "mozilla/dom/CSSPrimitiveValueBinding.h" +#include "mozilla/dom/CSSStyleDeclarationBinding.h" +#include "mozilla/dom/CSSStyleSheetBinding.h" +#include "mozilla/dom/CSSValueBinding.h" +#include "mozilla/dom/CSSValueListBinding.h" +#include "mozilla/dom/CustomEventBinding.h" +#ifdef MOZ_WEBRTC +#include "mozilla/dom/DataChannelBinding.h" +#endif +#include "mozilla/dom/DataContainerEventBinding.h" +#include "mozilla/dom/DataTransferBinding.h" +#include "mozilla/dom/DOMCursorBinding.h" +#include "mozilla/dom/DOMExceptionBinding.h" +#include "mozilla/dom/DOMParserBinding.h" +#include "mozilla/dom/DOMRequestBinding.h" +#include "mozilla/dom/DocumentBinding.h" +#include "mozilla/dom/DocumentFragmentBinding.h" +#include "mozilla/dom/DocumentTypeBinding.h" +#include "mozilla/dom/DocumentBinding.h" +#include "mozilla/dom/DragEventBinding.h" +#include "mozilla/dom/ElementBinding.h" +#include "mozilla/dom/EventBinding.h" +#include "mozilla/dom/EventTargetBinding.h" +#include "mozilla/dom/FileListBinding.h" +#include "mozilla/dom/FocusEventBinding.h" +#include "mozilla/dom/FormDataBinding.h" +#include "mozilla/dom/HistoryBinding.h" +#include "mozilla/dom/HTMLAnchorElementBinding.h" +#include "mozilla/dom/HTMLAppletElementBinding.h" +#include "mozilla/dom/HTMLAreaElementBinding.h" +#include "mozilla/dom/HTMLBaseElementBinding.h" +#include "mozilla/dom/HTMLBodyElementBinding.h" +#include "mozilla/dom/HTMLButtonElementBinding.h" +#include "mozilla/dom/HTMLCanvasElementBinding.h" +#include "mozilla/dom/HTMLCollectionBinding.h" +#include "mozilla/dom/HTMLDirectoryElementBinding.h" +#include "mozilla/dom/HTMLDocumentBinding.h" +#include "mozilla/dom/HTMLElementBinding.h" +#include "mozilla/dom/HTMLEmbedElementBinding.h" +#include "mozilla/dom/HTMLFieldSetElementBinding.h" +#include "mozilla/dom/HTMLFormElementBinding.h" +#include "mozilla/dom/HTMLFrameElementBinding.h" +#include "mozilla/dom/HTMLFrameSetElementBinding.h" +#include "mozilla/dom/HTMLHRElementBinding.h" +#include "mozilla/dom/HTMLHeadElementBinding.h" +#include "mozilla/dom/HTMLHtmlElementBinding.h" +#include "mozilla/dom/HTMLIFrameElementBinding.h" +#include "mozilla/dom/HTMLImageElementBinding.h" +#include "mozilla/dom/HTMLInputElementBinding.h" +#include "mozilla/dom/HTMLLIElementBinding.h" +#include "mozilla/dom/HTMLLabelElementBinding.h" +#include "mozilla/dom/HTMLLinkElementBinding.h" +#include "mozilla/dom/HTMLMapElementBinding.h" +#include "mozilla/dom/HTMLMediaElementBinding.h" +#include "mozilla/dom/HTMLMenuElementBinding.h" +#include "mozilla/dom/HTMLMenuItemElementBinding.h" +#include "mozilla/dom/HTMLMetaElementBinding.h" +#include "mozilla/dom/HTMLOListElementBinding.h" +#include "mozilla/dom/HTMLObjectElementBinding.h" +#include "mozilla/dom/HTMLOptGroupElementBinding.h" +#include "mozilla/dom/HTMLOptionElementBinding.h" +#include "mozilla/dom/HTMLOptionsCollectionBinding.h" +#include "mozilla/dom/HTMLParagraphElementBinding.h" +#include "mozilla/dom/HTMLPreElementBinding.h" +#include "mozilla/dom/HTMLQuoteElementBinding.h" +#include "mozilla/dom/HTMLScriptElementBinding.h" +#include "mozilla/dom/HTMLSelectElementBinding.h" +#include "mozilla/dom/HTMLSourceElementBinding.h" +#include "mozilla/dom/HTMLStyleElementBinding.h" +#include "mozilla/dom/HTMLTableCellElementBinding.h" +#include "mozilla/dom/HTMLTextAreaElementBinding.h" +#include "mozilla/dom/HTMLUListElementBinding.h" +#include "mozilla/dom/KeyEventBinding.h" +#include "mozilla/dom/ListBoxObjectBinding.h" +#include "mozilla/dom/MediaListBinding.h" +#include "mozilla/dom/MessageEventBinding.h" +#include "mozilla/dom/MenuBoxObjectBinding.h" +#include "mozilla/dom/MouseEventBinding.h" +#include "mozilla/dom/MouseScrollEventBinding.h" +#include "mozilla/dom/MutationEventBinding.h" +#include "mozilla/dom/NamedNodeMapBinding.h" +#include "mozilla/dom/NodeIteratorBinding.h" +#include "mozilla/dom/NodeBinding.h" +#include "mozilla/dom/NotifyPaintEventBinding.h" +#include "mozilla/dom/EventBinding.h" +#include "mozilla/dom/OfflineResourceListBinding.h" +#include "mozilla/dom/PaintRequestBinding.h" +#include "mozilla/dom/PositionErrorBinding.h" +#include "mozilla/dom/ProcessingInstructionBinding.h" +#include "mozilla/dom/RangeBinding.h" +#include "mozilla/dom/RectBinding.h" +#include "mozilla/dom/ScreenBinding.h" +#include "mozilla/dom/ScrollBoxObjectBinding.h" +#include "mozilla/dom/SelectionBinding.h" +#include "mozilla/dom/ScrollAreaEventBinding.h" +#include "mozilla/dom/SimpleGestureEventBinding.h" +#include "mozilla/dom/StorageEventBinding.h" +#include "mozilla/dom/StyleSheetBinding.h" +#include "mozilla/dom/StyleSheetListBinding.h" +#include "mozilla/dom/SVGElementBinding.h" +#include "mozilla/dom/SVGLengthBinding.h" +#include "mozilla/dom/TextBinding.h" +#include "mozilla/dom/TimeEventBinding.h" +#include "mozilla/dom/TimeRangesBinding.h" +#include "mozilla/dom/TransitionEventBinding.h" +#include "mozilla/dom/TreeBoxObjectBinding.h" +#include "mozilla/dom/TreeWalkerBinding.h" +#include "mozilla/dom/UIEventBinding.h" +#include "mozilla/dom/ValidityStateBinding.h" +#include "mozilla/dom/WheelEventBinding.h" +#include "mozilla/dom/XMLDocumentBinding.h" +#include "mozilla/dom/XMLHttpRequestEventTargetBinding.h" +#include "mozilla/dom/XMLHttpRequestUploadBinding.h" +#include "mozilla/dom/XMLSerializerBinding.h" +#include "mozilla/dom/XPathEvaluatorBinding.h" +#include "mozilla/dom/XPathResultBinding.h" +#include "mozilla/dom/XULCommandEventBinding.h" +#include "mozilla/dom/XULDocumentBinding.h" +#include "mozilla/dom/XULElementBinding.h" + +using namespace mozilla; + +struct ComponentsInterfaceShimEntry { + constexpr + ComponentsInterfaceShimEntry(const char* aName, const nsIID& aIID, + const dom::NativePropertyHooks* aNativePropHooks) + : geckoName(aName), iid(aIID), nativePropHooks(aNativePropHooks) {} + + const char *geckoName; + const nsIID& iid; + const dom::NativePropertyHooks* nativePropHooks; +}; + +#define DEFINE_SHIM_WITH_CUSTOM_INTERFACE(geckoName, domName) \ + { #geckoName, NS_GET_IID(geckoName), \ + mozilla::dom::domName ## Binding::sNativePropertyHooks } +#define DEFINE_SHIM(name) \ + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOM ## name, name) + +/** + * These shim entries allow us to make old XPIDL interfaces implementing DOM + * APIs as non-scriptable in order to save some runtime memory on Firefox OS, + * without breaking the entries under Components.interfaces which might both + * be used by our code and add-ons. Specifically, the shim entries provide + * the following: + * + * * Components.interfaces.nsIFoo entries. These entries basically work + * almost exactly as the usual ones that you would get through the + * XPIDL machinery. Specifically, they have the right name, they reflect + * the right IID, and they will work properly when passed to QueryInterface. + * + * * Components.interfaces.nsIFoo.CONSTANT values. These entries will have + * the right name and the right value for most integer types. Note that + * support for non-numerical constants is untested and will probably not + * work out of the box. + * + * FAQ: + * * When should I add an entry to the list here? + * Only if you're making an XPIDL interfaces which has a corresponding + * WebIDL interface non-scriptable. + * * When should I remove an entry from this list? + * If you are completely removing an XPIDL interface from the code base. If + * you forget to do so, the compiler will remind you. + * * How should I add an entry to the list here? + * First, make sure that the XPIDL interface in question is non-scriptable + * and also has a corresponding WebIDL interface. Then, add two include + * entries above, one for the XPIDL interface and one for the WebIDL + * interface, and add a shim entry below. If the name of the XPIDL + * interface only has an "nsIDOM" prefix prepended to the WebIDL name, you + * can use the DEFINE_SHIM macro and pass in the name of the WebIDL + * interface. Otherwise, use DEFINE_SHIM_WITH_CUSTOM_INTERFACE. + */ + +const ComponentsInterfaceShimEntry kComponentsInterfaceShimMap[] = +{ + DEFINE_SHIM(AnimationEvent), + DEFINE_SHIM(Attr), + DEFINE_SHIM(BeforeUnloadEvent), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIBrowserBoxObject, ContainerBoxObject), + DEFINE_SHIM(CanvasRenderingContext2D), + DEFINE_SHIM(CDATASection), + DEFINE_SHIM(CharacterData), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMClientRect, DOMRectReadOnly), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMClientRectList, DOMRectList), + DEFINE_SHIM(ClipboardEvent), + DEFINE_SHIM(CommandEvent), + DEFINE_SHIM(Comment), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIContainerBoxObject, ContainerBoxObject), + DEFINE_SHIM(CSSPrimitiveValue), + DEFINE_SHIM(CSSStyleDeclaration), + DEFINE_SHIM(CSSStyleSheet), + DEFINE_SHIM(CSSValue), + DEFINE_SHIM(CSSValueList), + DEFINE_SHIM(CustomEvent), +#ifdef MOZ_WEBRTC + DEFINE_SHIM(DataChannel), +#endif + DEFINE_SHIM(DataContainerEvent), + DEFINE_SHIM(DataTransfer), + DEFINE_SHIM(DOMCursor), + DEFINE_SHIM(DOMException), + DEFINE_SHIM(DOMRequest), + DEFINE_SHIM(Document), + DEFINE_SHIM(DocumentFragment), + DEFINE_SHIM(DocumentType), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMDocumentXBL, Document), + DEFINE_SHIM(DragEvent), + DEFINE_SHIM(Element), + DEFINE_SHIM(Event), + DEFINE_SHIM(EventTarget), + DEFINE_SHIM(FileList), + DEFINE_SHIM(FocusEvent), + DEFINE_SHIM(FormData), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMGeoPositionError, PositionError), + DEFINE_SHIM(History), + DEFINE_SHIM(HTMLAnchorElement), + DEFINE_SHIM(HTMLAppletElement), + DEFINE_SHIM(HTMLAreaElement), + DEFINE_SHIM(HTMLBaseElement), + DEFINE_SHIM(HTMLBodyElement), + DEFINE_SHIM(HTMLButtonElement), + DEFINE_SHIM(HTMLCanvasElement), + DEFINE_SHIM(HTMLCollection), + DEFINE_SHIM(HTMLDirectoryElement), + DEFINE_SHIM(HTMLDocument), + DEFINE_SHIM(HTMLElement), + DEFINE_SHIM(HTMLEmbedElement), + DEFINE_SHIM(HTMLFieldSetElement), + DEFINE_SHIM(HTMLFormElement), + DEFINE_SHIM(HTMLFrameElement), + DEFINE_SHIM(HTMLFrameSetElement), + DEFINE_SHIM(HTMLHRElement), + DEFINE_SHIM(HTMLHeadElement), + DEFINE_SHIM(HTMLHtmlElement), + DEFINE_SHIM(HTMLIFrameElement), + DEFINE_SHIM(HTMLImageElement), + DEFINE_SHIM(HTMLInputElement), + DEFINE_SHIM(HTMLLIElement), + DEFINE_SHIM(HTMLLabelElement), + DEFINE_SHIM(HTMLLinkElement), + DEFINE_SHIM(HTMLMapElement), + DEFINE_SHIM(HTMLMediaElement), + DEFINE_SHIM(HTMLMenuElement), + DEFINE_SHIM(HTMLMenuItemElement), + DEFINE_SHIM(HTMLMetaElement), + DEFINE_SHIM(HTMLOListElement), + DEFINE_SHIM(HTMLObjectElement), + DEFINE_SHIM(HTMLOptGroupElement), + DEFINE_SHIM(HTMLOptionElement), + DEFINE_SHIM(HTMLOptionsCollection), + DEFINE_SHIM(HTMLParagraphElement), + DEFINE_SHIM(HTMLPreElement), + DEFINE_SHIM(HTMLQuoteElement), + DEFINE_SHIM(HTMLScriptElement), + DEFINE_SHIM(HTMLSelectElement), + DEFINE_SHIM(HTMLSourceElement), + DEFINE_SHIM(HTMLStyleElement), + DEFINE_SHIM(HTMLTableCellElement), + DEFINE_SHIM(HTMLTextAreaElement), + DEFINE_SHIM(HTMLUListElement), + DEFINE_SHIM(KeyEvent), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIListBoxObject, ListBoxObject), + DEFINE_SHIM(MediaList), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIMenuBoxObject, MenuBoxObject), + DEFINE_SHIM(MouseEvent), + DEFINE_SHIM(MouseScrollEvent), + DEFINE_SHIM(MutationEvent), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMMozNamedAttrMap, NamedNodeMap), + DEFINE_SHIM(NodeIterator), + DEFINE_SHIM(Node), + DEFINE_SHIM(NotifyPaintEvent), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMNSEvent, Event), + DEFINE_SHIM(OfflineResourceList), + DEFINE_SHIM(PaintRequest), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMParser, DOMParser), + DEFINE_SHIM(ProcessingInstruction), + DEFINE_SHIM(Range), + DEFINE_SHIM(Rect), + DEFINE_SHIM(Screen), + DEFINE_SHIM(ScrollAreaEvent), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIScrollBoxObject, ScrollBoxObject), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMSerializer, XMLSerializer), + DEFINE_SHIM(SimpleGestureEvent), + DEFINE_SHIM(StyleSheet), + DEFINE_SHIM(StyleSheetList), + DEFINE_SHIM(SVGElement), + DEFINE_SHIM(SVGLength), + DEFINE_SHIM(Text), + DEFINE_SHIM(TimeEvent), + DEFINE_SHIM(TimeRanges), + DEFINE_SHIM(TransitionEvent), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsITreeBoxObject, TreeBoxObject), + DEFINE_SHIM(TreeWalker), + DEFINE_SHIM(UIEvent), + DEFINE_SHIM(ValidityState), + DEFINE_SHIM(WheelEvent), + DEFINE_SHIM(XMLDocument), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIXMLHttpRequestEventTarget, XMLHttpRequestEventTarget), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIXMLHttpRequestUpload, XMLHttpRequestUpload), + DEFINE_SHIM(XPathEvaluator), + DEFINE_SHIM(XPathResult), + DEFINE_SHIM(XULCommandEvent), + DEFINE_SHIM(XULDocument), + DEFINE_SHIM(XULElement), + DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsISelection, Selection), +}; + +#undef DEFINE_SHIM +#undef DEFINE_SHIM_WITH_CUSTOM_INTERFACE + +NS_IMPL_ISUPPORTS(ShimInterfaceInfo, nsISupports, nsIInterfaceInfo) + +already_AddRefed<ShimInterfaceInfo> +ShimInterfaceInfo::MaybeConstruct(const char* aName, JSContext* cx) +{ + RefPtr<ShimInterfaceInfo> info; + for (uint32_t i = 0; i < ArrayLength(kComponentsInterfaceShimMap); ++i) { + if (!strcmp(aName, kComponentsInterfaceShimMap[i].geckoName)) { + const ComponentsInterfaceShimEntry& shimEntry = + kComponentsInterfaceShimMap[i]; + info = new ShimInterfaceInfo(shimEntry.iid, + shimEntry.geckoName, + shimEntry.nativePropHooks); + break; + } + } + return info.forget(); +} + +ShimInterfaceInfo::ShimInterfaceInfo(const nsIID& aIID, + const char* aName, + const mozilla::dom::NativePropertyHooks* aNativePropHooks) + : mIID(aIID) + , mName(aName) + , mNativePropHooks(aNativePropHooks) +{ +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetName(char** aName) +{ + *aName = ToNewCString(mName); + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetInterfaceIID(nsIID** aIID) +{ + *aIID = static_cast<nsIID*> (nsMemory::Clone(&mIID, sizeof(mIID))); + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::IsScriptable(bool* aRetVal) +{ + // This class should pretend that the interface is scriptable because + // that's what nsJSIID assumes. + *aRetVal = true; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::IsBuiltinClass(bool* aRetVal) +{ + *aRetVal = true; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::IsMainProcessScriptableOnly(bool* aRetVal) +{ + *aRetVal = false; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetParent(nsIInterfaceInfo** aParent) +{ + *aParent = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetMethodCount(uint16_t* aCount) +{ + // Pretend we don't have any methods. + *aCount = 0; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetConstantCount(uint16_t* aCount) +{ + // We assume that we never have interfaces with more than UINT16_MAX + // constants defined on them. + uint16_t count = 0; + + // NOTE: The structure of this loop must be kept in sync with the loop + // in GetConstant. + const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks; + do { + const mozilla::dom::NativeProperties* props[] = { + propHooks->mNativeProperties.regular, + propHooks->mNativeProperties.chromeOnly + }; + for (size_t i = 0; i < ArrayLength(props); ++i) { + auto prop = props[i]; + if (prop && prop->HasConstants()) { + for (auto cs = prop->Constants()->specs; cs->name; ++cs) { + // We have found one constant here. We explicitly do not + // bother calling isEnabled() here because it's OK to define + // potentially extra constants on these shim interfaces. + ++count; + } + } + } + } while ((propHooks = propHooks->mProtoHooks)); + *aCount = count; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetMethodInfo(uint16_t aIndex, const nsXPTMethodInfo** aInfo) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetMethodInfoForName(const char* aName, uint16_t* aIndex, const nsXPTMethodInfo** aInfo) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetConstant(uint16_t aIndex, JS::MutableHandleValue aConstant, + char** aName) +{ + // We assume that we never have interfaces with more than UINT16_MAX + // constants defined on them. + uint16_t index = 0; + + // NOTE: The structure of this loop must be kept in sync with the loop + // in GetConstantCount. + const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks; + do { + const mozilla::dom::NativeProperties* props[] = { + propHooks->mNativeProperties.regular, + propHooks->mNativeProperties.chromeOnly + }; + for (size_t i = 0; i < ArrayLength(props); ++i) { + auto prop = props[i]; + if (prop && prop->HasConstants()) { + for (auto cs = prop->Constants()->specs; cs->name; ++cs) { + // We have found one constant here. We explicitly do not + // bother calling isEnabled() here because it's OK to define + // potentially extra constants on these shim interfaces. + if (index == aIndex) { + aConstant.set(cs->value); + *aName = ToNewCString(nsDependentCString(cs->name)); + return NS_OK; + } + ++index; + } + } + } + } while ((propHooks = propHooks->mProtoHooks)); + + // aIndex was bigger than the number of constants we have. + return NS_ERROR_INVALID_ARG; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetInfoForParam(uint16_t aIndex, const nsXPTParamInfo* aParam, nsIInterfaceInfo** aRetVal) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetIIDForParam(uint16_t aIndex, const nsXPTParamInfo* aParam, nsIID** aRetVal) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetTypeForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint16_t aDimension, nsXPTType* aRetVal) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetSizeIsArgNumberForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint16_t aDimension, uint8_t* aRetVal) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint8_t* aRetVal) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +ShimInterfaceInfo::IsIID(const nsIID* aIID, bool* aRetVal) +{ + *aRetVal = mIID.Equals(*aIID); + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetNameShared(const char** aName) +{ + *aName = mName.get(); + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::GetIIDShared(const nsIID** aIID) +{ + *aIID = &mIID; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::IsFunction(bool* aRetVal) +{ + *aRetVal = false; + return NS_OK; +} + +NS_IMETHODIMP +ShimInterfaceInfo::HasAncestor(const nsIID* aIID, bool* aRetVal) +{ + *aRetVal = false; + return NS_OK; +} + +NS_IMETHODIMP_(nsresult) +ShimInterfaceInfo::GetIIDForParamNoAlloc(uint16_t aIndex, const nsXPTParamInfo* aInfo, nsIID* aIID) +{ + MOZ_ASSERT(false, "This should never be called"); + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/xpcom/reflect/xptinfo/ShimInterfaceInfo.h b/xpcom/reflect/xptinfo/ShimInterfaceInfo.h new file mode 100644 index 000000000..868f503a5 --- /dev/null +++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=78: + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ShimInterfaceInfo_h +#define ShimInterfaceInfo_h + +#include "mozilla/Attributes.h" +#include "nsIInterfaceInfo.h" +#include "nsString.h" +#include "nsID.h" +#include "nsTArray.h" +#include "xptinfo.h" +#include "nsAutoPtr.h" +#include "js/RootingAPI.h" + +namespace mozilla { +namespace dom { +struct NativePropertyHooks; +} // namespace dom +} // namespace mozilla + +class ShimInterfaceInfo final : public nsIInterfaceInfo +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIINTERFACEINFO + + // Construct a ShimInterfaceInfo object if we have a shim available for aName. + // Otherwise, returns nullptr. + static already_AddRefed<ShimInterfaceInfo> + MaybeConstruct(const char* aName, JSContext* cx); + +private: + ShimInterfaceInfo(const nsIID& aIID, + const char* aName, + const mozilla::dom::NativePropertyHooks* aNativePropHooks); + + ~ShimInterfaceInfo() {} + +private: + nsIID mIID; + nsAutoCString mName; + const mozilla::dom::NativePropertyHooks* mNativePropHooks; +}; + +#endif diff --git a/xpcom/reflect/xptinfo/TODO b/xpcom/reflect/xptinfo/TODO new file mode 100644 index 000000000..50215a4fb --- /dev/null +++ b/xpcom/reflect/xptinfo/TODO @@ -0,0 +1,20 @@ +/* jband - 03/24/00 - */ + +- DOCS +- improve error handling + - should some errors really be warnings? + - should autoreg support additional channel to receive warnings so that + an installer can decide whether or not to accept the consequences of + leaving the newly installed files in place? +- verification of interfaces (warnings and/or errors) + - verify that repeated interfaces are identical in all ways + - verify that interface names are always one-to-one with iids +- check for truncated xpt files and version problems + - http://bugzilla.mozilla.org/show_bug.cgi?id=33193 +- TESTS! + - e.g. verify the merge stuff really works for various inputs. + - we really need a set of .xpt and .zip files and code that does an array + of autoreg and interfaceinof use activitities to test various corners + of the system. +- better autoreg logging +- use only 32 bits for file size? diff --git a/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h b/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h new file mode 100644 index 000000000..e72153ad2 --- /dev/null +++ b/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=4 et sw=4 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_XPTInterfaceInfoManager_h_ +#define mozilla_XPTInterfaceInfoManager_h_ + +#include "nsIInterfaceInfoManager.h" +#include "nsIMemoryReporter.h" + +#include "mozilla/MemoryReporting.h" +#include "mozilla/Mutex.h" +#include "mozilla/ReentrantMonitor.h" +#include "nsDataHashtable.h" + +template<typename T> class nsCOMArray; +class nsIMemoryReporter; +struct XPTHeader; +struct XPTInterfaceDirectoryEntry; +class xptiInterfaceEntry; +class xptiInterfaceInfo; +class xptiTypelibGuts; + +namespace mozilla { + +class XPTInterfaceInfoManager final + : public nsIInterfaceInfoManager + , public nsIMemoryReporter +{ + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIINTERFACEINFOMANAGER + NS_DECL_NSIMEMORYREPORTER + +public: + // GetSingleton() is infallible + static XPTInterfaceInfoManager* GetSingleton(); + static void FreeInterfaceInfoManager(); + + void GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces); + + void RegisterBuffer(char *buf, uint32_t length); + + static Mutex& GetResolveLock() + { + return GetSingleton()->mResolveLock; + } + + xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid); + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); + +private: + XPTInterfaceInfoManager(); + ~XPTInterfaceInfoManager(); + + void InitMemoryReporter(); + + void RegisterXPTHeader(XPTHeader* aHeader); + + // idx is the index of this interface in the XPTHeader + void VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface, + uint16_t idx, + xptiTypelibGuts* typelib); + +private: + + class xptiWorkingSet + { + public: + xptiWorkingSet(); + ~xptiWorkingSet(); + + bool IsValid() const; + + void InvalidateInterfaceInfos(); + void ClearHashTables(); + + // utility methods... + + enum {NOT_FOUND = 0xffffffff}; + + // Directory stuff... + + uint32_t GetDirectoryCount(); + nsresult GetCloneOfDirectoryAt(uint32_t i, nsIFile** dir); + nsresult GetDirectoryAt(uint32_t i, nsIFile** dir); + bool FindDirectory(nsIFile* dir, uint32_t* index); + bool FindDirectoryOfFile(nsIFile* file, uint32_t* index); + bool DirectoryAtMatchesPersistentDescriptor(uint32_t i, const char* desc); + + private: + uint32_t mFileCount; + uint32_t mMaxFileCount; + + public: + // XXX make these private with accessors + // mTableMonitor must be held across: + // * any read from or write to mIIDTable or mNameTable + // * any writing to the links between an xptiInterfaceEntry + // and its xptiInterfaceInfo (mEntry/mInfo) + mozilla::ReentrantMonitor mTableReentrantMonitor; + nsDataHashtable<nsIDHashKey, xptiInterfaceEntry*> mIIDTable; + nsDataHashtable<nsDepCharHashKey, xptiInterfaceEntry*> mNameTable; + }; + + // XXX xptiInterfaceInfo want's to poke at the working set itself + friend class ::xptiInterfaceInfo; + friend class ::xptiInterfaceEntry; + friend class ::xptiTypelibGuts; + + xptiWorkingSet mWorkingSet; + Mutex mResolveLock; +}; + +} // namespace mozilla + +#endif diff --git a/xpcom/reflect/xptinfo/moz.build b/xpcom/reflect/xptinfo/moz.build new file mode 100644 index 000000000..320949782 --- /dev/null +++ b/xpcom/reflect/xptinfo/moz.build @@ -0,0 +1,37 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +UNIFIED_SOURCES += [ + 'ShimInterfaceInfo.cpp', + 'xptiInterfaceInfo.cpp', + 'xptiInterfaceInfoManager.cpp', + 'xptiTypelibGuts.cpp', + 'xptiWorkingSet.cpp', +] + +XPIDL_SOURCES += [ + 'nsIInterfaceInfo.idl', + 'nsIInterfaceInfoManager.idl', +] + +XPIDL_MODULE = 'xpcom_xpti' + +EXPORTS += [ + 'xptinfo.h', +] + +EXPORTS.mozilla += [ + 'XPTInterfaceInfoManager.h', +] + +LOCAL_INCLUDES += [ + '/dom/base', +] + +FINAL_LIBRARY = 'xul' + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] diff --git a/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl b/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl new file mode 100644 index 000000000..8b902d5ee --- /dev/null +++ b/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* The nsIInterfaceInfo public declaration. */ + + +#include "nsISupports.idl" + +// forward declaration of non-XPCOM types + +[ptr] native nsXPTMethodInfoPtr(nsXPTMethodInfo); +[ptr] native nsXPTParamInfoPtr(nsXPTParamInfo); + native nsXPTType(nsXPTType); + +// We bend the rules to do a [shared] nsIID (but this is never scriptable) +[ptr] native nsIIDPtrShared(nsIID); + +%{C++ +class nsXPTMethodInfo; +class nsXPTParamInfo; +class nsXPTType; +%} + +[builtinclass, uuid(3820e663-8e22-4789-b470-56bcf7083f2b)] +interface nsIInterfaceInfo : nsISupports +{ + readonly attribute string name; + readonly attribute nsIIDPtr InterfaceIID; + + boolean isScriptable(); + boolean isBuiltinClass(); + + readonly attribute nsIInterfaceInfo parent; + + /** + * These include counts for parent (and all ancestors). + */ + readonly attribute uint16_t methodCount; + readonly attribute uint16_t constantCount; + + /** + * These include methods and constants for parent (and all ancestors). + * + * These do *not* make copies ***explicit bending of XPCOM rules***. + */ + + void getMethodInfo(in uint16_t index, + [shared, retval] out nsXPTMethodInfoPtr info); + + void getMethodInfoForName(in string methodName, out uint16_t index, + [shared, retval] out nsXPTMethodInfoPtr info); + + void getConstant(in uint16_t index, + out jsval constant, + out string name); + + + /** + * Get the interface information or iid associated with a param of some + * method in this interface. + */ + + nsIInterfaceInfo getInfoForParam(in uint16_t methodIndex, + [const] in nsXPTParamInfoPtr param); + + nsIIDPtr getIIDForParam(in uint16_t methodIndex, + [const] in nsXPTParamInfoPtr param); + + + /** + * These do *not* make copies ***explicit bending of XPCOM rules***. + */ + + nsXPTType getTypeForParam(in uint16_t methodIndex, + [const] in nsXPTParamInfoPtr param, + in uint16_t dimension); + + uint8_t getSizeIsArgNumberForParam(in uint16_t methodIndex, + [const] in nsXPTParamInfoPtr param, + in uint16_t dimension); + + uint8_t getInterfaceIsArgNumberForParam(in uint16_t methodIndex, + [const] in nsXPTParamInfoPtr param); + + boolean isIID(in nsIIDPtr IID); + + void getNameShared([shared,retval] out string name); + void getIIDShared([shared,retval] out nsIIDPtrShared iid); + + boolean isFunction(); + + boolean hasAncestor(in nsIIDPtr iid); + + [notxpcom] nsresult getIIDForParamNoAlloc(in uint16_t methodIndex, + [const] in nsXPTParamInfoPtr param, + out nsIID iid); + + boolean isMainProcessScriptableOnly(); +}; diff --git a/xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl b/xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl new file mode 100644 index 000000000..bc63aed49 --- /dev/null +++ b/xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* The nsIInterfaceInfoManager public declaration. */ + + +#include "nsISupports.idl" + +interface nsIInterfaceInfo; + +[builtinclass, uuid(1d53d8d9-1d92-428f-b5cc-198b55e897d7)] +interface nsIInterfaceInfoManager : nsISupports +{ + nsIInterfaceInfo getInfoForIID(in nsIIDPtr iid); + nsIInterfaceInfo getInfoForName(in string name); +}; + +%{C++ +#define NS_INTERFACEINFOMANAGER_SERVICE_CID \ + { /* 13bef784-f8e0-4f96-85c1-09f9ef4f9a19 */ \ + 0x13bef784, 0xf8e0, 0x4f96, \ + {0x85, 0xc1, 0x09, 0xf9, 0xef, 0x4f, 0x9a, 0x19} } + +#define NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID \ + "@mozilla.org/xpti/interfaceinfomanager-service;1" +%} diff --git a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp new file mode 100644 index 000000000..8ea80fda1 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp @@ -0,0 +1,742 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */ + +#include "xptiprivate.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/XPTInterfaceInfoManager.h" +#include "mozilla/PodOperations.h" +#include "jsapi.h" + +using namespace mozilla; + +/* static */ xptiInterfaceEntry* +xptiInterfaceEntry::Create(const char* name, const nsID& iid, + XPTInterfaceDescriptor* aDescriptor, + xptiTypelibGuts* aTypelib) +{ + int namelen = strlen(name); + void* place = + XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry) + namelen); + if (!place) { + return nullptr; + } + return new (place) xptiInterfaceEntry(name, namelen, iid, aDescriptor, + aTypelib); +} + +xptiInterfaceEntry::xptiInterfaceEntry(const char* name, + size_t nameLength, + const nsID& iid, + XPTInterfaceDescriptor* aDescriptor, + xptiTypelibGuts* aTypelib) + : mIID(iid) + , mDescriptor(aDescriptor) + , mTypelib(aTypelib) + , mParent(nullptr) + , mInfo(nullptr) + , mMethodBaseIndex(0) + , mConstantBaseIndex(0) + , mFlags(0) +{ + memcpy(mName, name, nameLength); + SetResolvedState(PARTIALLY_RESOLVED); +} + +bool +xptiInterfaceEntry::Resolve() +{ + MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock()); + return ResolveLocked(); +} + +bool +xptiInterfaceEntry::ResolveLocked() +{ + int resolvedState = GetResolveState(); + + if(resolvedState == FULLY_RESOLVED) + return true; + if(resolvedState == RESOLVE_FAILED) + return false; + + NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!"); + + // Finish out resolution by finding parent and Resolving it so + // we can set the info we get from it. + + uint16_t parent_index = mDescriptor->parent_interface; + + if(parent_index) + { + xptiInterfaceEntry* parent = + mTypelib->GetEntryAt(parent_index - 1); + + if(!parent || !parent->EnsureResolvedLocked()) + { + SetResolvedState(RESOLVE_FAILED); + return false; + } + + mParent = parent; + if (parent->GetHasNotXPCOMFlag()) { + SetHasNotXPCOMFlag(); + } else { + for (uint16_t idx = 0; idx < mDescriptor->num_methods; ++idx) { + nsXPTMethodInfo* method = reinterpret_cast<nsXPTMethodInfo*>( + mDescriptor->method_descriptors + idx); + if (method->IsNotXPCOM()) { + SetHasNotXPCOMFlag(); + break; + } + } + } + + + mMethodBaseIndex = + parent->mMethodBaseIndex + + parent->mDescriptor->num_methods; + + mConstantBaseIndex = + parent->mConstantBaseIndex + + parent->mDescriptor->num_constants; + + } + LOG_RESOLVE(("+ complete resolve of %s\n", mName)); + + SetResolvedState(FULLY_RESOLVED); + return true; +} + +/**************************************************/ +// These non-virtual methods handle the delegated nsIInterfaceInfo methods. + +nsresult +xptiInterfaceEntry::GetName(char **name) +{ + // It is not necessary to Resolve because this info is read from manifest. + *name = (char*) nsMemory::Clone(mName, strlen(mName)+1); + return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY; +} + +nsresult +xptiInterfaceEntry::GetIID(nsIID **iid) +{ + // It is not necessary to Resolve because this info is read from manifest. + *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID)); + return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY; +} + +nsresult +xptiInterfaceEntry::IsScriptable(bool* result) +{ + // It is not necessary to Resolve because this info is read from manifest. + *result = GetScriptableFlag(); + return NS_OK; +} + +nsresult +xptiInterfaceEntry::IsFunction(bool* result) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + *result = XPT_ID_IS_FUNCTION(mDescriptor->flags); + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetMethodCount(uint16_t* count) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + *count = mMethodBaseIndex + + mDescriptor->num_methods; + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetConstantCount(uint16_t* count) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(!count) + return NS_ERROR_UNEXPECTED; + + *count = mConstantBaseIndex + + mDescriptor->num_constants; + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetMethodInfo(uint16_t index, const nsXPTMethodInfo** info) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(index < mMethodBaseIndex) + return mParent->GetMethodInfo(index, info); + + if(index >= mMethodBaseIndex + + mDescriptor->num_methods) + { + NS_ERROR("bad param"); + *info = nullptr; + return NS_ERROR_INVALID_ARG; + } + + // else... + *info = reinterpret_cast<nsXPTMethodInfo*> + (&mDescriptor->method_descriptors[index - mMethodBaseIndex]); + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16_t *index, + const nsXPTMethodInfo** result) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + // This is a slow algorithm, but this is not expected to be called much. + for(uint16_t i = 0; i < mDescriptor->num_methods; ++i) + { + const nsXPTMethodInfo* info; + info = reinterpret_cast<nsXPTMethodInfo*> + (&mDescriptor-> + method_descriptors[i]); + if (PL_strcmp(methodName, info->GetName()) == 0) { + *index = i + mMethodBaseIndex; + *result = info; + return NS_OK; + } + } + + if(mParent) + return mParent->GetMethodInfoForName(methodName, index, result); + else + { + *index = 0; + *result = 0; + return NS_ERROR_INVALID_ARG; + } +} + +nsresult +xptiInterfaceEntry::GetConstant(uint16_t index, JS::MutableHandleValue constant, + char** name) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(index < mConstantBaseIndex) + return mParent->GetConstant(index, constant, name); + + if(index >= mConstantBaseIndex + + mDescriptor->num_constants) + { + NS_PRECONDITION(0, "bad param"); + return NS_ERROR_INVALID_ARG; + } + + const auto& c = mDescriptor->const_descriptors[index - mConstantBaseIndex]; + AutoJSContext cx; + JS::Rooted<JS::Value> v(cx); + v.setUndefined(); + + switch (c.type.prefix.flags) { + case nsXPTType::T_I8: + { + v.setInt32(c.value.i8); + break; + } + case nsXPTType::T_U8: + { + v.setInt32(c.value.ui8); + break; + } + case nsXPTType::T_I16: + { + v.setInt32(c.value.i16); + break; + } + case nsXPTType::T_U16: + { + v.setInt32(c.value.ui16); + break; + } + case nsXPTType::T_I32: + { + v = JS_NumberValue(c.value.i32); + break; + } + case nsXPTType::T_U32: + { + v = JS_NumberValue(c.value.ui32); + break; + } + default: + { +#ifdef DEBUG + NS_ERROR("Non-numeric constant found in interface."); +#endif + } + } + + constant.set(v); + *name = ToNewCString(nsDependentCString(c.name)); + + return NS_OK; +} + +// this is a private helper + +nsresult +xptiInterfaceEntry::GetInterfaceIndexForParam(uint16_t methodIndex, + const nsXPTParamInfo* param, + uint16_t* interfaceIndex) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(methodIndex < mMethodBaseIndex) + return mParent->GetInterfaceIndexForParam(methodIndex, param, + interfaceIndex); + + if(methodIndex >= mMethodBaseIndex + + mDescriptor->num_methods) + { + NS_ERROR("bad param"); + return NS_ERROR_INVALID_ARG; + } + + const XPTTypeDescriptor *td = ¶m->type; + + while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { + td = &mDescriptor->additional_types[td->u.array.additional_type]; + } + + if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) { + NS_ERROR("not an interface"); + return NS_ERROR_INVALID_ARG; + } + + *interfaceIndex = (td->u.iface.iface_hi8 << 8) | td->u.iface.iface_lo8; + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetEntryForParam(uint16_t methodIndex, + const nsXPTParamInfo * param, + xptiInterfaceEntry** entry) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(methodIndex < mMethodBaseIndex) + return mParent->GetEntryForParam(methodIndex, param, entry); + + uint16_t interfaceIndex = 0; + nsresult rv = GetInterfaceIndexForParam(methodIndex, param, + &interfaceIndex); + if (NS_FAILED(rv)) { + return rv; + } + + xptiInterfaceEntry* theEntry = mTypelib->GetEntryAt(interfaceIndex - 1); + + // This can happen if a declared interface is not available at runtime. + if(!theEntry) + { + *entry = nullptr; + return NS_ERROR_FAILURE; + } + + *entry = theEntry; + return NS_OK; +} + +already_AddRefed<ShimInterfaceInfo> +xptiInterfaceEntry::GetShimForParam(uint16_t methodIndex, + const nsXPTParamInfo* param) +{ + if(methodIndex < mMethodBaseIndex) { + return mParent->GetShimForParam(methodIndex, param); + } + + uint16_t interfaceIndex = 0; + nsresult rv = GetInterfaceIndexForParam(methodIndex, param, + &interfaceIndex); + if (NS_FAILED(rv)) { + return nullptr; + } + + const char* shimName = mTypelib->GetEntryNameAt(interfaceIndex - 1); + RefPtr<ShimInterfaceInfo> shim = + ShimInterfaceInfo::MaybeConstruct(shimName, nullptr); + return shim.forget(); +} + +nsresult +xptiInterfaceEntry::GetInfoForParam(uint16_t methodIndex, + const nsXPTParamInfo *param, + nsIInterfaceInfo** info) +{ + xptiInterfaceEntry* entry; + nsresult rv = GetEntryForParam(methodIndex, param, &entry); + if (NS_FAILED(rv)) { + RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param); + if (!shim) { + return rv; + } + + shim.forget(info); + return NS_OK; + } + + *info = entry->InterfaceInfo().take(); + + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetIIDForParam(uint16_t methodIndex, + const nsXPTParamInfo* param, nsIID** iid) +{ + xptiInterfaceEntry* entry; + nsresult rv = GetEntryForParam(methodIndex, param, &entry); + if (NS_FAILED(rv)) { + RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param); + if (!shim) { + return rv; + } + + return shim->GetInterfaceIID(iid); + } + return entry->GetIID(iid); +} + +nsresult +xptiInterfaceEntry::GetIIDForParamNoAlloc(uint16_t methodIndex, + const nsXPTParamInfo * param, + nsIID *iid) +{ + xptiInterfaceEntry* entry; + nsresult rv = GetEntryForParam(methodIndex, param, &entry); + if (NS_FAILED(rv)) { + RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param); + if (!shim) { + return rv; + } + + const nsIID* shimIID; + DebugOnly<nsresult> rv2 = shim->GetIIDShared(&shimIID); + MOZ_ASSERT(NS_SUCCEEDED(rv2)); + *iid = *shimIID; + return NS_OK; + } + *iid = entry->mIID; + return NS_OK; +} + +// this is a private helper +nsresult +xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param, + uint16_t dimension, + const XPTTypeDescriptor** type) +{ + NS_ASSERTION(IsFullyResolved(), "bad state"); + + const XPTTypeDescriptor *td = ¶m->type; + const XPTTypeDescriptor *additional_types = + mDescriptor->additional_types; + + for (uint16_t i = 0; i < dimension; i++) { + if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) { + NS_ERROR("bad dimension"); + return NS_ERROR_INVALID_ARG; + } + td = &additional_types[td->u.array.additional_type]; + } + + *type = td; + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex, + const nsXPTParamInfo* param, + uint16_t dimension, + nsXPTType* type) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(methodIndex < mMethodBaseIndex) + return mParent-> + GetTypeForParam(methodIndex, param, dimension, type); + + if(methodIndex >= mMethodBaseIndex + + mDescriptor->num_methods) + { + NS_ERROR("bad index"); + return NS_ERROR_INVALID_ARG; + } + + const XPTTypeDescriptor *td; + + if(dimension) { + nsresult rv = GetTypeInArray(param, dimension, &td); + if(NS_FAILED(rv)) + return rv; + } + else + td = ¶m->type; + + *type = nsXPTType(td->prefix); + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16_t methodIndex, + const nsXPTParamInfo* param, + uint16_t dimension, + uint8_t* argnum) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(methodIndex < mMethodBaseIndex) + return mParent-> + GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum); + + if(methodIndex >= mMethodBaseIndex + + mDescriptor->num_methods) + { + NS_ERROR("bad index"); + return NS_ERROR_INVALID_ARG; + } + + const XPTTypeDescriptor *td; + + if(dimension) { + nsresult rv = GetTypeInArray(param, dimension, &td); + if(NS_FAILED(rv)) + return rv; + } + else + td = ¶m->type; + + // verify that this is a type that has size_is + switch (XPT_TDP_TAG(td->prefix)) { + case TD_ARRAY: + *argnum = td->u.array.argnum; + break; + case TD_PSTRING_SIZE_IS: + case TD_PWSTRING_SIZE_IS: + *argnum = td->u.pstring_is.argnum; + break; + default: + NS_ERROR("not a size_is"); + return NS_ERROR_INVALID_ARG; + } + + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex, + const nsXPTParamInfo* param, + uint8_t* argnum) +{ + if(!EnsureResolved()) + return NS_ERROR_UNEXPECTED; + + if(methodIndex < mMethodBaseIndex) + return mParent-> + GetInterfaceIsArgNumberForParam(methodIndex, param, argnum); + + if(methodIndex >= mMethodBaseIndex + + mDescriptor->num_methods) + { + NS_ERROR("bad index"); + return NS_ERROR_INVALID_ARG; + } + + const XPTTypeDescriptor *td = ¶m->type; + + while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { + td = &mDescriptor->additional_types[td->u.array.additional_type]; + } + + if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) { + NS_ERROR("not an iid_is"); + return NS_ERROR_INVALID_ARG; + } + + *argnum = td->u.interface_is.argnum; + return NS_OK; +} + +nsresult +xptiInterfaceEntry::IsIID(const nsIID * iid, bool *_retval) +{ + // It is not necessary to Resolve because this info is read from manifest. + *_retval = mIID.Equals(*iid); + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetNameShared(const char **name) +{ + // It is not necessary to Resolve because this info is read from manifest. + *name = mName; + return NS_OK; +} + +nsresult +xptiInterfaceEntry::GetIIDShared(const nsIID * *iid) +{ + // It is not necessary to Resolve because this info is read from manifest. + *iid = &mIID; + return NS_OK; +} + +nsresult +xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval) +{ + *_retval = false; + + for(xptiInterfaceEntry* current = this; + current; + current = current->mParent) + { + if(current->mIID.Equals(*iid)) + { + *_retval = true; + break; + } + if(!current->EnsureResolved()) + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +/***************************************************/ + +already_AddRefed<xptiInterfaceInfo> +xptiInterfaceEntry::InterfaceInfo() +{ +#ifdef DEBUG + XPTInterfaceInfoManager::GetSingleton()->mWorkingSet.mTableReentrantMonitor. + AssertCurrentThreadIn(); +#endif + + if(!mInfo) + { + mInfo = new xptiInterfaceInfo(this); + } + + RefPtr<xptiInterfaceInfo> info = mInfo; + return info.forget(); +} + +void +xptiInterfaceEntry::LockedInvalidateInterfaceInfo() +{ + if(mInfo) + { + mInfo->Invalidate(); + mInfo = nullptr; + } +} + +bool +xptiInterfaceInfo::BuildParent() +{ + mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::GetSingleton()-> + mWorkingSet.mTableReentrantMonitor); + NS_ASSERTION(mEntry && + mEntry->IsFullyResolved() && + !mParent && + mEntry->Parent(), + "bad BuildParent call"); + mParent = mEntry->Parent()->InterfaceInfo(); + return true; +} + +/***************************************************************************/ + +NS_IMPL_QUERY_INTERFACE(xptiInterfaceInfo, nsIInterfaceInfo) + +xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry) + : mEntry(entry) +{ +} + +xptiInterfaceInfo::~xptiInterfaceInfo() +{ + NS_ASSERTION(!mEntry, "bad state in dtor"); +} + +void +xptiInterfaceInfo::Invalidate() +{ + mParent = nullptr; + mEntry = nullptr; +} + +MozExternalRefCountType +xptiInterfaceInfo::AddRef(void) +{ + nsrefcnt cnt = ++mRefCnt; + NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this)); + return cnt; +} + +MozExternalRefCountType +xptiInterfaceInfo::Release(void) +{ + xptiInterfaceEntry* entry = mEntry; + nsrefcnt cnt = --mRefCnt; + NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo"); + if(!cnt) + { + mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager:: + GetSingleton()->mWorkingSet. + mTableReentrantMonitor); + + // If InterfaceInfo added and *released* a reference before we + // acquired the monitor then 'this' might already be dead. In that + // case we would not want to try to access any instance data. We + // would want to bail immediately. If 'this' is already dead then the + // entry will no longer have a pointer to 'this'. So, we can protect + // ourselves from danger without more aggressive locking. + if(entry && !entry->InterfaceInfoEquals(this)) + return 0; + + // If InterfaceInfo added a reference before we acquired the monitor + // then we want to bail out of here without destorying the object. + if(mRefCnt) + return 1; + + if(mEntry) + { + mEntry->LockedInterfaceInfoDeathNotification(); + mEntry = nullptr; + } + + delete this; + return 0; + } + return cnt; +} + +/***************************************************************************/ diff --git a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp new file mode 100644 index 000000000..600a99b94 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp @@ -0,0 +1,242 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implementation of xptiInterfaceInfoManager. */ + +#include "mozilla/XPTInterfaceInfoManager.h" + +#include "mozilla/FileUtils.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/StaticPtr.h" + +#include "xptiprivate.h" +#include "nsDependentString.h" +#include "nsString.h" +#include "nsArrayEnumerator.h" +#include "nsDirectoryService.h" +#include "nsIMemoryReporter.h" + +using namespace mozilla; + +NS_IMPL_ISUPPORTS( + XPTInterfaceInfoManager, + nsIInterfaceInfoManager, + nsIMemoryReporter) + +static StaticRefPtr<XPTInterfaceInfoManager> gInterfaceInfoManager; + +size_t +XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) +{ + size_t n = aMallocSizeOf(this); + ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor); + // The entries themselves are allocated out of an arena accounted + // for elsewhere, so don't measure them + n += mWorkingSet.mIIDTable.ShallowSizeOfExcludingThis(aMallocSizeOf); + n += mWorkingSet.mNameTable.ShallowSizeOfExcludingThis(aMallocSizeOf); + return n; +} + +MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf) + +NS_IMETHODIMP +XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, bool aAnonymize) +{ + size_t amount = SizeOfIncludingThis(XPTIMallocSizeOf); + + // Measure gXPTIStructArena here, too. This is a bit grotty because it + // doesn't belong to the XPTIInterfaceInfoManager, but there's no + // obviously better place to measure it. + amount += XPT_SizeOfArenaIncludingThis(gXPTIStructArena, XPTIMallocSizeOf); + + MOZ_COLLECT_REPORT( + "explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount, + "Memory used by the XPCOM typelib system."); + + return NS_OK; +} + +// static +XPTInterfaceInfoManager* +XPTInterfaceInfoManager::GetSingleton() +{ + if (!gInterfaceInfoManager) { + gInterfaceInfoManager = new XPTInterfaceInfoManager(); + gInterfaceInfoManager->InitMemoryReporter(); + } + return gInterfaceInfoManager; +} + +void +XPTInterfaceInfoManager::FreeInterfaceInfoManager() +{ + gInterfaceInfoManager = nullptr; +} + +XPTInterfaceInfoManager::XPTInterfaceInfoManager() + : mWorkingSet(), + mResolveLock("XPTInterfaceInfoManager.mResolveLock") +{ +} + +XPTInterfaceInfoManager::~XPTInterfaceInfoManager() +{ + // We only do this on shutdown of the service. + mWorkingSet.InvalidateInterfaceInfos(); + + UnregisterWeakMemoryReporter(this); +} + +void +XPTInterfaceInfoManager::InitMemoryReporter() +{ + RegisterWeakMemoryReporter(this); +} + +void +XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length) +{ + XPTState state; + XPT_InitXDRState(&state, buf, length); + + XPTCursor curs; + NotNull<XPTCursor*> cursor = WrapNotNull(&curs); + if (!XPT_MakeCursor(&state, XPT_HEADER, 0, cursor)) { + return; + } + + XPTHeader *header = nullptr; + if (XPT_DoHeader(gXPTIStructArena, cursor, &header)) { + RegisterXPTHeader(header); + } +} + +void +XPTInterfaceInfoManager::RegisterXPTHeader(XPTHeader* aHeader) +{ + if (aHeader->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) { + NS_ASSERTION(!aHeader->num_interfaces,"bad libxpt"); + LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION)); + } + + xptiTypelibGuts* typelib = xptiTypelibGuts::Create(aHeader); + + ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor); + for(uint16_t k = 0; k < aHeader->num_interfaces; k++) + VerifyAndAddEntryIfNew(aHeader->interface_directory + k, k, typelib); +} + +void +XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface, + uint16_t idx, + xptiTypelibGuts* typelib) +{ + if (!iface->interface_descriptor) + return; + + // The number of maximum methods is not arbitrary. It is the same value as + // in xpcom/reflect/xptcall/genstubs.pl; do not change this value + // without changing that one or you WILL see problems. + if (iface->interface_descriptor->num_methods > 250 && + !(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags))) { + NS_ASSERTION(0, "Too many methods to handle for the stub, cannot load"); + fprintf(stderr, "ignoring too large interface: %s\n", iface->name); + return; + } + + mWorkingSet.mTableReentrantMonitor.AssertCurrentThreadIn(); + xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->iid); + if (entry) { + // XXX validate this info to find possible inconsistencies + LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name)); + return; + } + + // Build a new xptiInterfaceEntry object and hook it up. + + entry = xptiInterfaceEntry::Create(iface->name, + iface->iid, + iface->interface_descriptor, + typelib); + if (!entry) + return; + + //XXX We should SetHeader too as part of the validation, no? + entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags)); + entry->SetBuiltinClassFlag(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags)); + entry->SetMainProcessScriptableOnlyFlag( + XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(iface->interface_descriptor->flags)); + + mWorkingSet.mIIDTable.Put(entry->IID(), entry); + mWorkingSet.mNameTable.Put(entry->GetTheName(), entry); + + typelib->SetEntryAt(idx, entry); + + LOG_AUTOREG((" added interface: %s\n", iface->name)); +} + +// this is a private helper +static nsresult +EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval) +{ + if (!entry) { + *_retval = nullptr; + return NS_ERROR_FAILURE; + } + + RefPtr<xptiInterfaceInfo> info = entry->InterfaceInfo(); + info.forget(_retval); + return NS_OK; +} + +xptiInterfaceEntry* +XPTInterfaceInfoManager::GetInterfaceEntryForIID(const nsIID *iid) +{ + ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor); + return mWorkingSet.mIIDTable.Get(*iid); +} + +NS_IMETHODIMP +XPTInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval) +{ + NS_ASSERTION(iid, "bad param"); + NS_ASSERTION(_retval, "bad param"); + + ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor); + xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid); + return EntryToInfo(entry, _retval); +} + +NS_IMETHODIMP +XPTInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval) +{ + NS_ASSERTION(name, "bad param"); + NS_ASSERTION(_retval, "bad param"); + + ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor); + xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name); + return EntryToInfo(entry, _retval); +} + +void +XPTInterfaceInfoManager::GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces) +{ + // I didn't want to incur the size overhead of using nsHashtable just to + // make building an enumerator easier. So, this code makes a snapshot of + // the table using an nsCOMArray and builds an enumerator for that. + // We can afford this transient cost. + + ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor); + aInterfaces.SetCapacity(mWorkingSet.mNameTable.Count()); + for (auto iter = mWorkingSet.mNameTable.Iter(); !iter.Done(); iter.Next()) { + xptiInterfaceEntry* entry = iter.UserData(); + if (entry->GetScriptableFlag()) { + nsCOMPtr<nsIInterfaceInfo> ii = entry->InterfaceInfo(); + aInterfaces.AppendElement(ii); + } + } +} diff --git a/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp new file mode 100644 index 000000000..e2965d0b1 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implementation of xptiTypelibGuts. */ + +#include "xptiprivate.h" +#include "mozilla/XPTInterfaceInfoManager.h" + +using namespace mozilla; + +// Ensure through static analysis that xptiTypelibGuts won't have a vtable. +template <class T> +class MOZ_NEEDS_NO_VTABLE_TYPE CheckNoVTable +{ +}; +CheckNoVTable<xptiTypelibGuts> gChecker; + +// static +xptiTypelibGuts* +xptiTypelibGuts::Create(XPTHeader* aHeader) +{ + NS_ASSERTION(aHeader, "bad param"); + size_t n = sizeof(xptiTypelibGuts) + + sizeof(xptiInterfaceEntry*) * (aHeader->num_interfaces - 1); + void* place = XPT_CALLOC8(gXPTIStructArena, n); + if (!place) + return nullptr; + return new(place) xptiTypelibGuts(aHeader); +} + +xptiInterfaceEntry* +xptiTypelibGuts::GetEntryAt(uint16_t i) +{ + static const nsID zeroIID = + { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }; + + NS_ASSERTION(mHeader, "bad state"); + NS_ASSERTION(i < GetEntryCount(), "bad index"); + + xptiInterfaceEntry* r = mEntryArray[i]; + if (r) + return r; + + XPTInterfaceDirectoryEntry* iface = mHeader->interface_directory + i; + + XPTInterfaceInfoManager::xptiWorkingSet& set = + XPTInterfaceInfoManager::GetSingleton()->mWorkingSet; + + { + ReentrantMonitorAutoEnter monitor(set.mTableReentrantMonitor); + if (iface->iid.Equals(zeroIID)) + r = set.mNameTable.Get(iface->name); + else + r = set.mIIDTable.Get(iface->iid); + } + + if (r) + SetEntryAt(i, r); + + return r; +} + +const char* +xptiTypelibGuts::GetEntryNameAt(uint16_t i) +{ + NS_ASSERTION(mHeader, "bad state"); + NS_ASSERTION(i < GetEntryCount(), "bad index"); + + XPTInterfaceDirectoryEntry* iface = mHeader->interface_directory + i; + + return iface->name; +} diff --git a/xpcom/reflect/xptinfo/xptiWorkingSet.cpp b/xpcom/reflect/xptinfo/xptiWorkingSet.cpp new file mode 100644 index 000000000..10f81a4b2 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptiWorkingSet.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implementation of xptiWorkingSet. */ + +#include "mozilla/XPTInterfaceInfoManager.h" + +#include "xptiprivate.h" +#include "nsString.h" + +using namespace mozilla; + +static const size_t XPTI_ARENA8_BLOCK_SIZE = 16 * 1024; +static const size_t XPTI_ARENA1_BLOCK_SIZE = 8 * 1024; + +static const uint32_t XPTI_HASHTABLE_LENGTH = 1024; + +XPTInterfaceInfoManager::xptiWorkingSet::xptiWorkingSet() + : mTableReentrantMonitor("xptiWorkingSet::mTableReentrantMonitor") + , mIIDTable(XPTI_HASHTABLE_LENGTH) + , mNameTable(XPTI_HASHTABLE_LENGTH) +{ + MOZ_COUNT_CTOR(xptiWorkingSet); + + gXPTIStructArena = XPT_NewArena(XPTI_ARENA8_BLOCK_SIZE, + XPTI_ARENA1_BLOCK_SIZE); +} + +void +XPTInterfaceInfoManager::xptiWorkingSet::InvalidateInterfaceInfos() +{ + ReentrantMonitorAutoEnter monitor(mTableReentrantMonitor); + for (auto iter = mNameTable.Iter(); !iter.Done(); iter.Next()) { + xptiInterfaceEntry* entry = iter.UserData(); + entry->LockedInvalidateInterfaceInfo(); + } +} + +XPTInterfaceInfoManager::xptiWorkingSet::~xptiWorkingSet() +{ + MOZ_COUNT_DTOR(xptiWorkingSet); + + // Only destroy the arena if we're doing leak stats. Why waste shutdown + // time touching pages if we don't have to? +#ifdef NS_FREE_PERMANENT_DATA + XPT_DestroyArena(gXPTIStructArena); +#endif +} + +XPTArena* gXPTIStructArena; diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h new file mode 100644 index 000000000..1207a42bb --- /dev/null +++ b/xpcom/reflect/xptinfo/xptinfo.h @@ -0,0 +1,236 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* XPTI_PUBLIC_API and XPTI_GetInterfaceInfoManager declarations. */ + +#ifndef xptiinfo_h___ +#define xptiinfo_h___ + +#include "nscore.h" +#include "xpt_struct.h" + +// Flyweight wrapper classes for xpt_struct.h structs. +// Everything here is dependent upon - and sensitive to changes in - +// xpcom/typelib/xpt/xpt_struct.h! + +class nsXPTType : public XPTTypeDescriptorPrefix +{ +// NO DATA - this a flyweight wrapper +public: + nsXPTType() + {} // random contents + MOZ_IMPLICIT nsXPTType(const XPTTypeDescriptorPrefix& prefix) + {*(XPTTypeDescriptorPrefix*)this = prefix;} + + MOZ_IMPLICIT nsXPTType(const uint8_t& prefix) + {*(uint8_t*)this = prefix;} + + nsXPTType& operator=(uint8_t val) + {flags = val; return *this;} + + nsXPTType& operator=(const nsXPTType& other) + {flags = other.flags; return *this;} + + operator uint8_t() const + {return flags;} + + // 'Arithmetic' here roughly means that the value is self-contained and + // doesn't depend on anything else in memory (ie: not a pointer, not an + // XPCOM object, not a jsval, etc). + // + // Supposedly this terminology comes from Harbison/Steele, but it's still + // a rather crappy name. We'd change it if it wasn't used all over the + // place in xptcall. :-( + bool IsArithmetic() const + {return flags <= T_WCHAR;} + + // We used to abuse 'pointer' flag bit in typelib format quite extensively. + // We've gotten rid of most of the cases, but there's still a fair amount + // of refactoring to be done in XPCWrappedJSClass before we can safely stop + // asking about this. In the mean time, we've got a temporary version of + // IsPointer() that should be equivalent to what's in the typelib. + bool deprecated_IsPointer() const + {return !IsArithmetic() && TagPart() != T_JSVAL;} + + bool IsInterfacePointer() const + { switch (TagPart()) { + default: + return false; + case T_INTERFACE: + case T_INTERFACE_IS: + return true; + } + } + + bool IsArray() const + {return TagPart() == T_ARRAY;} + + // 'Dependent' means that params of this type are dependent upon other + // params. e.g. an T_INTERFACE_IS is dependent upon some other param at + // runtime to say what the interface type of this param really is. + bool IsDependent() const + { switch (TagPart()) { + default: + return false; + case T_INTERFACE_IS: + case TD_ARRAY: + case T_PSTRING_SIZE_IS: + case T_PWSTRING_SIZE_IS: + return true; + } + } + + uint8_t TagPart() const + {return (uint8_t) (flags & XPT_TDP_TAGMASK);} + + enum + { + T_I8 = TD_INT8 , + T_I16 = TD_INT16 , + T_I32 = TD_INT32 , + T_I64 = TD_INT64 , + T_U8 = TD_UINT8 , + T_U16 = TD_UINT16 , + T_U32 = TD_UINT32 , + T_U64 = TD_UINT64 , + T_FLOAT = TD_FLOAT , + T_DOUBLE = TD_DOUBLE , + T_BOOL = TD_BOOL , + T_CHAR = TD_CHAR , + T_WCHAR = TD_WCHAR , + T_VOID = TD_VOID , + T_IID = TD_PNSIID , + T_DOMSTRING = TD_DOMSTRING , + T_CHAR_STR = TD_PSTRING , + T_WCHAR_STR = TD_PWSTRING , + T_INTERFACE = TD_INTERFACE_TYPE , + T_INTERFACE_IS = TD_INTERFACE_IS_TYPE, + T_ARRAY = TD_ARRAY , + T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS , + T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS , + T_UTF8STRING = TD_UTF8STRING , + T_CSTRING = TD_CSTRING , + T_ASTRING = TD_ASTRING , + T_JSVAL = TD_JSVAL + }; +// NO DATA - this a flyweight wrapper +}; + +class nsXPTParamInfo : public XPTParamDescriptor +{ +// NO DATA - this a flyweight wrapper +public: + MOZ_IMPLICIT nsXPTParamInfo(const XPTParamDescriptor& desc) + {*(XPTParamDescriptor*)this = desc;} + + + bool IsIn() const {return 0 != (XPT_PD_IS_IN(flags));} + bool IsOut() const {return 0 != (XPT_PD_IS_OUT(flags));} + bool IsRetval() const {return 0 != (XPT_PD_IS_RETVAL(flags));} + bool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));} + + // Dipper types are one of the more inscrutable aspects of xpidl. In a + // nutshell, dippers are empty container objects, created and passed by + // the caller, and filled by the callee. The callee receives a fully- + // formed object, and thus does not have to construct anything. But + // the object is functionally empty, and the callee is responsible for + // putting something useful inside of it. + // + // XPIDL decides which types to make dippers. The list of these types + // is given in the isDipperType() function in typelib.py, and is currently + // limited to 4 string types. + // + // When a dipper type is declared as an 'out' parameter, xpidl internally + // converts it to an 'in', and sets the XPT_PD_DIPPER flag on it. For this + // reason, dipper types are sometimes referred to as 'out parameters + // masquerading as in'. The burden of maintaining this illusion falls mostly + // on XPConnect, which creates the empty containers, and harvest the results + // after the call. + bool IsDipper() const {return 0 != (XPT_PD_IS_DIPPER(flags));} + bool IsOptional() const {return 0 != (XPT_PD_IS_OPTIONAL(flags));} + const nsXPTType GetType() const {return type.prefix;} + + bool IsStringClass() const { + switch (GetType().TagPart()) { + case nsXPTType::T_ASTRING: + case nsXPTType::T_DOMSTRING: + case nsXPTType::T_UTF8STRING: + case nsXPTType::T_CSTRING: + return true; + default: + return false; + } + } + + // Whether this parameter is passed indirectly on the stack. This mainly + // applies to out/inout params, but we use it unconditionally for certain + // types. + bool IsIndirect() const {return IsOut() || + GetType().TagPart() == nsXPTType::T_JSVAL;} + + // NOTE: other activities on types are done via methods on nsIInterfaceInfo + +private: + nsXPTParamInfo(); // no implementation +// NO DATA - this a flyweight wrapper +}; + +class nsXPTMethodInfo : public XPTMethodDescriptor +{ +// NO DATA - this a flyweight wrapper +public: + MOZ_IMPLICIT nsXPTMethodInfo(const XPTMethodDescriptor& desc) + {*(XPTMethodDescriptor*)this = desc;} + + bool IsGetter() const {return 0 != (XPT_MD_IS_GETTER(flags) );} + bool IsSetter() const {return 0 != (XPT_MD_IS_SETTER(flags) );} + bool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));} + bool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );} + bool WantsOptArgc() const {return 0 != (XPT_MD_WANTS_OPT_ARGC(flags));} + bool WantsContext() const {return 0 != (XPT_MD_WANTS_CONTEXT(flags));} + const char* GetName() const {return name;} + uint8_t GetParamCount() const {return num_args;} + /* idx was index before I got _sick_ of the warnings on Unix, sorry jband */ + const nsXPTParamInfo GetParam(uint8_t idx) const + { + NS_PRECONDITION(idx < GetParamCount(),"bad arg"); + return params[idx]; + } + const nsXPTParamInfo GetResult() const + {return result;} +private: + nsXPTMethodInfo(); // no implementation +// NO DATA - this a flyweight wrapper +}; + + +// forward declaration +struct nsXPTCMiniVariant; + +class nsXPTConstant : public XPTConstDescriptor +{ +// NO DATA - this a flyweight wrapper +public: + MOZ_IMPLICIT nsXPTConstant(const XPTConstDescriptor& desc) + {*(XPTConstDescriptor*)this = desc;} + + const char* GetName() const + {return name;} + + const nsXPTType GetType() const + {return type.prefix;} + + // XXX this is ugly. But sometimes you gotta do what you gotta do. + // A reinterpret_cast won't do the trick here. And this plain C cast + // works correctly and is safe enough. + // See http://bugzilla.mozilla.org/show_bug.cgi?id=49641 + const nsXPTCMiniVariant* GetValue() const + {return (nsXPTCMiniVariant*) &value;} +private: + nsXPTConstant(); // no implementation +// NO DATA - this a flyweight wrapper +}; + +#endif /* xptiinfo_h___ */ diff --git a/xpcom/reflect/xptinfo/xptiprivate.h b/xpcom/reflect/xptinfo/xptiprivate.h new file mode 100644 index 000000000..c32ef9c77 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptiprivate.h @@ -0,0 +1,394 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Library-private header for Interface Info system. */ + +#ifndef xptiprivate_h___ +#define xptiprivate_h___ + +#include "nscore.h" +#include <new> +#include "nsISupports.h" + +// this after nsISupports, to pick up IID +// so that xpt stuff doesn't try to define it itself... +#include "xpt_struct.h" +#include "xpt_xdr.h" + +#include "nsIInterfaceInfo.h" +#include "nsIInterfaceInfoManager.h" +#include "xptinfo.h" +#include "ShimInterfaceInfo.h" + +#include "nsIServiceManager.h" +#include "nsIFile.h" +#include "nsIDirectoryService.h" +#include "nsDirectoryServiceDefs.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsIWeakReference.h" + +#include "mozilla/ReentrantMonitor.h" +#include "mozilla/Mutex.h" +#include "mozilla/Attributes.h" + +#include "js/TypeDecls.h" + +#include "nsCRT.h" +#include "nsMemory.h" + +#include "nsCOMArray.h" +#include "nsQuickSort.h" + +#include "nsXPIDLString.h" + +#include "nsIInputStream.h" + +#include "nsHashKeys.h" +#include "nsDataHashtable.h" +#include "plstr.h" +#include "prprf.h" +#include "prio.h" +#include "prtime.h" +#include "prenv.h" + +#include <stdio.h> +#include <stdarg.h> + +/***************************************************************************/ + +#if 0 && defined(DEBUG_jband) +#define LOG_RESOLVE(x) printf x +#define LOG_LOAD(x) printf x +#define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0) +#else +#define LOG_RESOLVE(x) ((void)0) +#define LOG_LOAD(x) ((void)0) +#define LOG_AUTOREG(x) ((void)0) +#endif + +#if 1 && defined(DEBUG_jband) +#define SHOW_INFO_COUNT_STATS +#endif + +/***************************************************************************/ + +class xptiInterfaceInfo; +class xptiInterfaceEntry; +class xptiTypelibGuts; + +extern XPTArena* gXPTIStructArena; + +/***************************************************************************/ + +/***************************************************************************/ + +// No virtuals. +// These are always constructed in the struct arena using placement new. +// dtor need not be called. + +class xptiTypelibGuts +{ +public: + static xptiTypelibGuts* Create(XPTHeader* aHeader); + + XPTHeader* GetHeader() {return mHeader;} + uint16_t GetEntryCount() const {return mHeader->num_interfaces;} + + void SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr) + { + NS_ASSERTION(mHeader,"bad state!"); + NS_ASSERTION(i < GetEntryCount(),"bad param!"); + mEntryArray[i] = ptr; + } + + xptiInterfaceEntry* GetEntryAt(uint16_t i); + const char* GetEntryNameAt(uint16_t i); + +private: + explicit xptiTypelibGuts(XPTHeader* aHeader) + : mHeader(aHeader) + { } + ~xptiTypelibGuts(); + +private: + XPTHeader* mHeader; // hold pointer into arena + xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit. +}; + +/***************************************************************************/ + +/***************************************************************************/ + +// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value +// and a set of bitflags in one 8bit value. See below. + +class xptiInfoFlags +{ + enum {STATE_MASK = 3}; +public: + explicit xptiInfoFlags(uint8_t n) : mData(n) {} + xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {} + + static uint8_t GetStateMask() + {return uint8_t(STATE_MASK);} + + void Clear() + {mData = 0;} + + uint8_t GetData() const + {return mData;} + + uint8_t GetState() const + {return mData & GetStateMask();} + + void SetState(uint8_t state) + {mData &= ~GetStateMask(); mData |= state;} + + void SetFlagBit(uint8_t flag, bool on) + {if(on) + mData |= ~GetStateMask() & flag; + else + mData &= GetStateMask() | ~flag;} + + bool GetFlagBit(uint8_t flag) const + {return (mData & flag) ? true : false;} + +private: + uint8_t mData; +}; + +/****************************************************/ + +// No virtual methods. +// We always create in the struct arena and construct using "placement new". +// No members need dtor calls. + +class xptiInterfaceEntry +{ +public: + static xptiInterfaceEntry* Create(const char* name, + const nsID& iid, + XPTInterfaceDescriptor* aDescriptor, + xptiTypelibGuts* aTypelib); + + enum { + PARTIALLY_RESOLVED = 1, + FULLY_RESOLVED = 2, + RESOLVE_FAILED = 3 + }; + + // Additional bit flags... + enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16, + MAIN_PROCESS_SCRIPTABLE_ONLY = 32}; + + uint8_t GetResolveState() const {return mFlags.GetState();} + + bool IsFullyResolved() const + {return GetResolveState() == (uint8_t) FULLY_RESOLVED;} + + void SetScriptableFlag(bool on) + {mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);} + bool GetScriptableFlag() const + {return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));} + void SetBuiltinClassFlag(bool on) + {mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);} + bool GetBuiltinClassFlag() const + {return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));} + void SetMainProcessScriptableOnlyFlag(bool on) + {mFlags.SetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY),on);} + bool GetMainProcessScriptableOnlyFlag() const + {return mFlags.GetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY));} + + + // AddRef/Release are special and are not considered for the NOTXPCOM flag. + void SetHasNotXPCOMFlag() + { + mFlags.SetFlagBit(HASNOTXPCOM, true); + } + bool GetHasNotXPCOMFlag() const + { + return mFlags.GetFlagBit(HASNOTXPCOM); + } + + const nsID* GetTheIID() const {return &mIID;} + const char* GetTheName() const {return mName;} + + bool EnsureResolved() + {return IsFullyResolved() ? true : Resolve();} + + already_AddRefed<xptiInterfaceInfo> InterfaceInfo(); + bool InterfaceInfoEquals(const xptiInterfaceInfo* info) const + {return info == mInfo;} + + void LockedInvalidateInterfaceInfo(); + void LockedInterfaceInfoDeathNotification() {mInfo = nullptr;} + + xptiInterfaceEntry* Parent() const { + NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?"); + return mParent; + } + + const nsID& IID() const { return mIID; } + + ////////////////////// + // These non-virtual methods handle the delegated nsIInterfaceInfo methods. + + nsresult GetName(char * *aName); + nsresult GetIID(nsIID * *aIID); + nsresult IsScriptable(bool *_retval); + nsresult IsBuiltinClass(bool *_retval) { + *_retval = GetBuiltinClassFlag(); + return NS_OK; + } + nsresult IsMainProcessScriptableOnly(bool *_retval) { + *_retval = GetMainProcessScriptableOnlyFlag(); + return NS_OK; + } + // Except this one. + //nsresult GetParent(nsIInterfaceInfo * *aParent); + nsresult GetMethodCount(uint16_t *aMethodCount); + nsresult GetConstantCount(uint16_t *aConstantCount); + nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info); + nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info); + nsresult GetConstant(uint16_t index, JS::MutableHandleValue, char** constant); + nsresult GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval); + nsresult GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval); + nsresult GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval); + nsresult GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval); + nsresult GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval); + nsresult IsIID(const nsIID * IID, bool *_retval); + nsresult GetNameShared(const char **name); + nsresult GetIIDShared(const nsIID * *iid); + nsresult IsFunction(bool *_retval); + nsresult HasAncestor(const nsIID * iid, bool *_retval); + nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid); + +private: + xptiInterfaceEntry(const char* name, + size_t nameLength, + const nsID& iid, + XPTInterfaceDescriptor* aDescriptor, + xptiTypelibGuts* aTypelib); + ~xptiInterfaceEntry(); + + void SetResolvedState(int state) + {mFlags.SetState(uint8_t(state));} + + bool Resolve(); + + // We only call these "*Locked" variants after locking. This is done to + // allow reentrace as files are loaded and various interfaces resolved + // without having to worry about the locked state. + + bool EnsureResolvedLocked() + {return IsFullyResolved() ? true : ResolveLocked();} + bool ResolveLocked(); + + // private helpers + + nsresult GetEntryForParam(uint16_t methodIndex, + const nsXPTParamInfo * param, + xptiInterfaceEntry** entry); + + nsresult GetTypeInArray(const nsXPTParamInfo* param, + uint16_t dimension, + const XPTTypeDescriptor** type); + + nsresult GetInterfaceIndexForParam(uint16_t methodIndex, + const nsXPTParamInfo* param, + uint16_t* interfaceIndex); + + already_AddRefed<ShimInterfaceInfo> + GetShimForParam(uint16_t methodIndex, const nsXPTParamInfo* param); + +private: + nsID mIID; + XPTInterfaceDescriptor* mDescriptor; + + xptiTypelibGuts* mTypelib; + + xptiInterfaceEntry* mParent; // Valid only when fully resolved + + xptiInterfaceInfo* MOZ_UNSAFE_REF("The safety of this pointer is ensured " + "by the semantics of xptiWorkingSet.") + mInfo; // May come and go. + + uint16_t mMethodBaseIndex; + uint16_t mConstantBaseIndex; + + xptiInfoFlags mFlags; + + char mName[1]; // Always last. Sized to fit. +}; + +class xptiInterfaceInfo final : public nsIInterfaceInfo +{ +public: + NS_DECL_THREADSAFE_ISUPPORTS + + // Use delegation to implement (most!) of nsIInterfaceInfo. + NS_IMETHOD GetName(char * *aName) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); } + NS_IMETHOD GetInterfaceIID(nsIID * *aIID) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); } + NS_IMETHOD IsScriptable(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); } + NS_IMETHOD IsBuiltinClass(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); } + NS_IMETHOD IsMainProcessScriptableOnly(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsMainProcessScriptableOnly(_retval); } + // Except this one. + NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) override + { + if(!EnsureResolved() || !EnsureParent()) + return NS_ERROR_UNEXPECTED; + NS_IF_ADDREF(*aParent = mParent); + return NS_OK; + } + NS_IMETHOD GetMethodCount(uint16_t *aMethodCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); } + NS_IMETHOD GetConstantCount(uint16_t *aConstantCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); } + NS_IMETHOD GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); } + NS_IMETHOD GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); } + NS_IMETHOD GetConstant(uint16_t index, JS::MutableHandleValue constant, char** name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant, name); } + NS_IMETHOD GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); } + NS_IMETHOD GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); } + NS_IMETHOD GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); } + NS_IMETHOD GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); } + NS_IMETHOD GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); } + NS_IMETHOD IsIID(const nsIID * IID, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); } + NS_IMETHOD GetNameShared(const char **name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); } + NS_IMETHOD GetIIDShared(const nsIID * *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); } + NS_IMETHOD IsFunction(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); } + NS_IMETHOD HasAncestor(const nsIID * iid, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); } + NS_IMETHOD GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); } + +public: + explicit xptiInterfaceInfo(xptiInterfaceEntry* entry); + + void Invalidate(); + +private: + + ~xptiInterfaceInfo(); + + // Note that mParent might still end up as nullptr if we don't have one. + bool EnsureParent() + { + NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call"); + return mParent || !mEntry->Parent() || BuildParent(); + } + + bool EnsureResolved() + { + return mEntry && mEntry->EnsureResolved(); + } + + bool BuildParent(); + + xptiInterfaceInfo(); // not implemented + +private: + xptiInterfaceEntry* mEntry; + RefPtr<xptiInterfaceInfo> mParent; +}; + +/***************************************************************************/ + +#endif /* xptiprivate_h___ */ |