summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/call.asm (renamed from bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm)124
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx135
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk2
-rw-r--r--bridges/source/cpp_uno/shared/vtablefactory.cxx24
4 files changed, 89 insertions, 196 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm
index 8d76b2f8a521..ae514fd065e2 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm
@@ -29,15 +29,18 @@
;; in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
;; instead of those above.
-;; This is the template source code for the trampoline generated by
-;; codeSnippet() in cpp2uno.cxx. codeSnippet() copies the code from
-;; this function, modifying it as necessary in a few places. The
-;; generated trampoline calls cpp_vtable_call() which then calls the
-;; actual UNO function.
+;; This is the function jumped to from the trampoline generated by
+;; codeSnippet() in cpp2uno.cxx. Here we call cpp_vtable_call() which
+;; then calls the actual UNO function.
-;; We keep this as a separate .asm file here so that it is easy to
-;; modify, and we don't need to laborously enter machine code into
-;; codeSnippet().
+;; The code snippet generated is called from "normal" C++ code which
+;; has no idea that it is calling dynamically generated code.
+
+;; The generated short code snippet is not covered by any function
+;; table and unwind info, but that doesn't matter, as the instructions
+;; in it are not really going to cause any exception. Once it jumps
+;; here it is covered by a function table, and the calls further down
+;; through cpp_vtable_call() can be unwound cleanly.
;; This is in a separate file for x86-64 as MSVC doesn't have in-line
;; assembly for x64.
@@ -73,9 +76,6 @@
;; information, for instance:
;; http://www.nynaeve.net/?p=11
-;; The code snippet generated is called from "normal" C++ code which
-;; has no idea that it is calling dynamically generated code.
-
typelib_TypeClass_FLOAT equ 10
typelib_TypeClass_DOUBLE equ 11
@@ -83,28 +83,7 @@ extern cpp_vtable_call: proc
.code
-;; Single instruction templates. For each register paramter, which can
-;; be either in an integer or floating-point register, either of two
-;; instruction sequences are used, either:
-;; mov qword ptr offset[rsp], reg
-;; nop
-;; or:
-;; movsd qwort ptr offset[rsp], xmmreg
-;;
-;; The nop in the integer case is so that both are of equal length
-
-fp_spill_templates:
-public fp_spill_templates
- movsd qword ptr (40+8)[rsp], xmm0
- movsd qword ptr (40+16)[rsp], xmm1
- movsd qword ptr (40+24)[rsp], xmm2
- movsd qword ptr (40+32)[rsp], xmm3
-fp_spill_templates_end:
-public fp_spill_templates_end
-
-;; The actual template function code here
-
-trampoline_template proc
+privateSnippetExecutor proc frame
;; Make stack frame. Re-align RSP at 16 bytes. We need just one
;; qword of stack for our own purposes: Where cpp_vtable_call()
@@ -113,76 +92,20 @@ trampoline_template proc
;; cpp_vtable_call()) to spill their register parameters.
sub rsp, 40
-trampoline_template_prolog_end:
-
- jmp trampoline_template_spill_params
-
- ;; We store the function table (with just one entry, for this function) and
- ;; the associated unwind info here at a known offset from the function start
- ;; so that we don't have to know separately where it is when we need to unregister it, but
- ;; can just use the known offset from the function start.
-
- align 4
- ;; See http://msdn.microsoft.com/en-us/library/ssa62fwe%28v=VS.90%29.aspx
-trampoline_template_function_table::
-public trampoline_template_function_table
- dword 0
- dword trampoline_template_end - trampoline_template
- dword unwind_info - trampoline_template
-unwind_info:
- byte 1
- byte trampoline_template_prolog_end - trampoline_template
- byte 1
- byte 0
- byte trampoline_template_prolog_end - trampoline_template
- byte 42h
-
-trampoline_template_spill_params::
-public trampoline_template_spill_params
-
- ;; Spill our register parameters. In the x64 Windows calling
- ;; convention the caller always has stack space allocated
- ;; where the callee can spill register parameters.
-
- ;; The default is integer moves, that are replaced in the
- ;; generated code snippet with floating-point moves for
- ;; floating-point parameters.
-
- mov qword ptr (40+8)[rsp], rcx
- nop
- mov qword ptr (40+16)[rsp], rdx
- nop
- mov qword ptr (40+24)[rsp], r8
- nop
- mov qword ptr (40+32)[rsp], r9
- nop
-trampoline_template_spill_params_end::
-public trampoline_template_spill_params_end
-
- ;; Call cpp_vtable_call() with 3 parameters:
-
- ;; 1 (rcx): nFunctionIndex
- ;; 2 (rdx): nVtableOffset
- ;; 3 (r8): pointer to where to store return value, followed by our
+ .allocstack (40)
+ .endprolog
+
+ ;; Call cpp_vtable_call() with 2 parameters:
+
+ ;; 1 (rcx): nOffsetAndIndex (already put there in code generated by codeSnippet)
+ ;; 2 (rdx): pointer to where to store return value, followed by our
;; return address (uninteresting to cpp_vtable_call()), followed
;; by our spilled register parameters, as stored above, followed
;; by the rest of our parameters, if any.
- mov rcx, 12345467890abcdeh ;; nFunctionIndex, actual value generated from
- ;; parameter to codeSnippet()
-trampoline_template_function_index::
-public trampoline_template_function_index
+ lea rdx, 32[rsp]
- mov rdx, 12345467890abcdeh ;; nVtableOffset, ditto
-trampoline_template_vtable_offset::
-public trampoline_template_vtable_offset
-
- lea r8, 32[rsp] ;; Where cpp_vtable_call() will store the return value
-
- mov rax, 12345467890abcdeh ;; cpp_vtable_call address, filled in by codeSnippet()
-trampoline_template_cpp_vtable_call::
-public trampoline_template_cpp_vtable_call
- call rax
+ call cpp_vtable_call
;; cpp_vtable_call() returns the typelib_TypeClass type of the
;; return value of the called UNO function
@@ -202,10 +125,7 @@ Lfloat:
Lepilogue:
add rsp, 40
ret
-trampoline_template_end::
-public trampoline_template_end
-
-trampoline_template endp
+privateSnippetExecutor endp
end
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
index 22e0c7467e15..38d48241d02c 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
@@ -228,10 +228,12 @@ static inline typelib_TypeClass cpp2uno_call(
//==================================================================================================
extern "C" typelib_TypeClass cpp_vtable_call(
- sal_Int32 nFunctionIndex,
- sal_Int32 nVtableOffset,
+ sal_Int64 nOffsetAndIndex,
void ** pStack )
{
+ sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF);
+ sal_Int32 nVtableOffset = ((nOffsetAndIndex >> 32) & 0xFFFFFFFF);
+
// pStack points to space for return value, after which
// follows our return address (uninteresting) then the spilled
// integer or floating-point register parameters from the call to
@@ -372,89 +374,84 @@ extern "C" typelib_TypeClass cpp_vtable_call(
}
//==================================================================================================
-extern "C" {
-
-// These are actually addresses in the code compiled from codeSnippet.asm
-extern char
- fp_spill_templates,
- fp_spill_templates_end,
- trampoline_template,
- trampoline_template_function_table,
- trampoline_template_spill_params,
- trampoline_template_spill_params_end,
- trampoline_template_function_index,
- trampoline_template_vtable_offset,
- trampoline_template_cpp_vtable_call,
- trampoline_template_end;
-}
-// Just the code
-int const codeSnippetSize =
- (int) (&trampoline_template_end - &trampoline_template);
+int const codeSnippetSize = 48;
+
+extern "C" char privateSnippetExecutor;
// This function generates the code that acts as a proxy for the UNO function to be called.
// The generated code does the following:
-// - Save register parametrs.
+// - Spills register parameters on stack
+// - Loads functionIndex and vtableOffset into scratch registers
+// - Jumps to privateSnippetExecutor
unsigned char * codeSnippet(
unsigned char * code,
char param_kind[4],
- sal_Int32 functionIndex,
- sal_Int32 vtableOffset,
+ sal_Int32 nFunctionIndex,
+ sal_Int32 nVtableOffset,
bool bHasHiddenParam )
{
- OSL_ASSERT( (&fp_spill_templates_end - &fp_spill_templates) ==
- (&trampoline_template_spill_params_end - &trampoline_template_spill_params) );
-
- OSL_ASSERT( ((&fp_spill_templates_end - &fp_spill_templates) / 4) * 4 ==
- (&fp_spill_templates_end - &fp_spill_templates) );
+ sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex );
+ unsigned char *p = code;
if ( bHasHiddenParam )
- functionIndex |= 0x80000000;
-
- int const one_spill_instruction_size =
- (int) ((&fp_spill_templates_end - &fp_spill_templates)) / 4;
+ nOffsetAndIndex |= 0x80000000;
- memcpy( code, &trampoline_template, codeSnippetSize );
-
- for (int i = 0; i < 4; ++i)
+ // Spill parameters
+ if ( param_kind[0] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
{
- if ( param_kind[i] == CPPU_CURRENT_NAMESPACE::REGPARAM_FLT )
- {
- memcpy (&trampoline_template_spill_params + i*one_spill_instruction_size,
- &fp_spill_templates + i*one_spill_instruction_size,
- one_spill_instruction_size);
- }
+ // mov qword ptr 8[rsp], rcx
+ *p++ = 0x48; *p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x08;
+ }
+ else
+ {
+ // movsd qword ptr 8[rsp], xmm0
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08;
+ }
+ if ( param_kind[1] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
+ {
+ // mov qword ptr 16[rsp], rdx
+ *p++ = 0x48; *p++ = 0x89; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10;
}
+ else
+ {
+ // movsd qword ptr 16[rsp], xmm1
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x10;
+ }
+ if ( param_kind[2] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
+ {
+ // mov qword ptr 24[rsp], r8
+ *p++ = 0x4C; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18;
+ }
+ else
+ {
+ // movsd qword ptr 24[rsp], xmm2
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18;
+ }
+ if ( param_kind[3] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
+ {
+ // mov qword ptr 32[rsp], r9
+ *p++ = 0x4C;*p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x20;
+ }
+ else
+ {
+ // movsd qword ptr 32[rsp], xmm3
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x5C; *p++ = 0x24; *p++ = 0x20;
+ }
+
+ // mov rcx, nOffsetAndIndex
+ *p++ = 0x48; *p++ = 0xB9;
+ *((sal_uInt64 *)p) = nOffsetAndIndex; p += 8;
+
+ // mov r11, privateSnippetExecutor
+ *p++ = 0x49; *p++ = 0xBB;
+ *((void **)p) = &privateSnippetExecutor; p += 8;
+
+ // jmp r11
+ *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
- ((sal_uInt64*) (code + (&trampoline_template_function_index
- - &trampoline_template)))[-1] =
- functionIndex;
- ((sal_uInt64*) (code + (&trampoline_template_vtable_offset
- - &trampoline_template)))[-1] =
- vtableOffset;
- ((void**) (code + (&trampoline_template_cpp_vtable_call
- - &trampoline_template)))[-1] =
- cpp_vtable_call;
-
- // Add unwind data for the dynamically generated function by
- // calling RtlAddFunctionTable().
-
- // The unwind data is inside the function code, at a fixed offset
- // from the function start. See codeSnippet.asm. Actually this is
- // unnecessarily complex, we could as well just allocate the
- // function table dynamically. But it doesn't hurt either, I
- // think.
-
- // The real problem now is that we need to remove the unwind data
- // with RtlDeleteFunctionTable() in freeExec() in
- // vtablefactory.cxx. See comment there.
-
- RUNTIME_FUNCTION *pFunTable =
- (RUNTIME_FUNCTION *) (code + (&trampoline_template_function_table
- - &trampoline_template));
-
- RtlAddFunctionTable( pFunTable, 1, (DWORD64) code );
+ OSL_ASSERT( p < code + codeSnippetSize );
return code + codeSnippetSize;
}
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
index e813fad0c4cc..7f73ebe4bba2 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
@@ -55,7 +55,7 @@ SLOFILES= \
$(SLO)$/uno2cpp.obj \
$(SLO)$/dllinit.obj \
$(SLO)$/except.obj \
- $(SLO)$/codeSnippet.obj
+ $(SLO)$/call.obj
NOOPTFILES= \
$(SLO)$/except.obj
diff --git a/bridges/source/cpp_uno/shared/vtablefactory.cxx b/bridges/source/cpp_uno/shared/vtablefactory.cxx
index f589c295f3a7..4b819632c863 100644
--- a/bridges/source/cpp_uno/shared/vtablefactory.cxx
+++ b/bridges/source/cpp_uno/shared/vtablefactory.cxx
@@ -125,14 +125,6 @@ extern "C" void * SAL_CALL allocExec(rtl_arena_type *, sal_Size * size) {
return p;
}
-#if defined SAL_W32
-extern "C" {
-extern char
- trampoline_template,
- trampoline_template_function_table;
-}
-#endif
-
extern "C" void SAL_CALL freeExec(
rtl_arena_type *, void * address, sal_Size size)
{
@@ -140,22 +132,6 @@ extern "C" void SAL_CALL freeExec(
munmap(static_cast< char * >(address), size);
#elif defined SAL_W32
(void) size; // unused
-
- // Remove the function table for the dynamically generated
- // function that was added in codeSnippet() in cpp2uno.cxx.
-
-#if 0
- // This is broken. address is not the address of a code
- // snippet. Each virtual memory region alocated with
- // VirtualAlloc() contains multiple generated code snippets. We
- // need to have a hash table from the base addresses of the region
- // to the function tables inside it.
-
- RUNTIME_FUNCTION *pFunTable =
- (RUNTIME_FUNCTION *) ((char *) address + (&trampoline_template_function_table - &trampoline_template));
- RtlDeleteFunctionTable( pFunTable );
-#endif
-
VirtualFree(address, 0, MEM_RELEASE);
#elif defined(SAL_OS2)
(void) DosFreeMem( address);