2011-01-17 03:52:12 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*************************************************************************
|
|
|
|
*
|
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
|
|
*
|
|
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
|
|
*
|
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
|
|
*
|
|
|
|
* This file is part of OpenOffice.org.
|
|
|
|
*
|
|
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
* only, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License version 3 for more details
|
|
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
|
|
* <http://www.openoffice.org/license.html>
|
|
|
|
* for a copy of the LGPLv3 License.
|
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
#include <malloc.h>
|
|
|
|
|
|
|
|
#include <com/sun/star/uno/genfunc.hxx>
|
|
|
|
#include <uno/data.h>
|
|
|
|
#include <typelib/typedescription.hxx>
|
|
|
|
|
|
|
|
#include "bridges/cpp_uno/shared/bridge.hxx"
|
|
|
|
#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
|
|
|
|
#include "bridges/cpp_uno/shared/types.hxx"
|
|
|
|
#include "bridges/cpp_uno/shared/vtablefactory.hxx"
|
|
|
|
|
|
|
|
#include "mscx.hxx"
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
using namespace ::com::sun::star::uno;
|
2011-01-17 03:52:12 +02:00
|
|
|
|
|
|
|
static inline typelib_TypeClass cpp2uno_call(
|
|
|
|
bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
|
2011-01-31 01:08:29 +02:00
|
|
|
const typelib_TypeDescription * pMemberTD,
|
2011-01-27 15:44:09 +02:00
|
|
|
typelib_TypeDescriptionReference * pReturnTypeRef, // NULL indicates void return
|
2011-01-31 01:08:29 +02:00
|
|
|
sal_Int32 nParams,
|
|
|
|
typelib_MethodParameter * pParams,
|
2011-01-27 15:44:09 +02:00
|
|
|
void ** pStack )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
// Return type
|
2011-01-29 01:40:06 +02:00
|
|
|
typelib_TypeDescription * pReturnTD = NULL;
|
2011-01-27 15:44:09 +02:00
|
|
|
if ( pReturnTypeRef )
|
2011-01-29 01:40:06 +02:00
|
|
|
TYPELIB_DANGER_GET( &pReturnTD, pReturnTypeRef );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
int nFirstRealParam = 3; // Index into pStack, past return
|
|
|
|
// value, return address and 'this'
|
|
|
|
// pointer.
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
void * pUnoReturn = NULL;
|
|
|
|
void * pCppReturn = NULL; // Complex return ptr: if != NULL && != pUnoReturn, reconversion need
|
|
|
|
|
2011-01-29 01:40:06 +02:00
|
|
|
if ( pReturnTD )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
if ( bridges::cpp_uno::shared::isSimpleType( pReturnTD ) )
|
|
|
|
{
|
|
|
|
pUnoReturn = pStack;
|
|
|
|
}
|
|
|
|
else
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
pCppReturn = pStack[nFirstRealParam++];
|
|
|
|
|
2011-01-29 01:40:06 +02:00
|
|
|
pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTD )
|
|
|
|
? alloca( pReturnTD->nSize )
|
2011-01-27 15:44:09 +02:00
|
|
|
: pCppReturn ); // direct way
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
void ** pCppIncomingParams = pStack + nFirstRealParam;
|
|
|
|
|
|
|
|
// Unlike this method for other archs, prefer clarity to
|
|
|
|
// micro-optimization, and allocate these array separately
|
|
|
|
|
|
|
|
// Parameters passed to the UNO function
|
|
|
|
void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
// Parameters received from C++
|
|
|
|
void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
// Indexes of values this have to be converted (interface conversion C++<=>UNO)
|
2011-01-27 15:44:09 +02:00
|
|
|
int * pTempIndexes =
|
|
|
|
(int *)alloca( sizeof(int) * nParams );
|
|
|
|
|
|
|
|
// Type descriptions for reconversions
|
2011-01-29 01:40:06 +02:00
|
|
|
typelib_TypeDescription ** ppTempParamTD =
|
2011-01-27 15:44:09 +02:00
|
|
|
(typelib_TypeDescription **)alloca( sizeof(void *) * nParams );
|
|
|
|
|
|
|
|
int nTempIndexes = 0;
|
|
|
|
|
|
|
|
for ( int nPos = 0; nPos < nParams; ++nPos )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
|
|
|
const typelib_MethodParameter & rParam = pParams[nPos];
|
|
|
|
|
2011-01-29 01:40:06 +02:00
|
|
|
typelib_TypeDescription * pParamTD = NULL;
|
|
|
|
TYPELIB_DANGER_GET( &pParamTD, rParam.pTypeRef );
|
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
if ( !rParam.bOut &&
|
|
|
|
bridges::cpp_uno::shared::isSimpleType( pParamTD ) )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
pCppArgs[nPos] = pUnoArgs[nPos] = pCppIncomingParams++;
|
2011-01-29 01:40:06 +02:00
|
|
|
|
|
|
|
TYPELIB_DANGER_RELEASE( pParamTD );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
else // ptr to complex value | ref
|
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
void * pCppStack;
|
|
|
|
|
|
|
|
pCppArgs[nPos] = pCppStack = *pCppIncomingParams++;
|
|
|
|
|
|
|
|
if ( !rParam.bIn ) // Pure out
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
// UNO out is unconstructed mem
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
pUnoArgs[nPos] = alloca( pParamTD->nSize );
|
2011-01-26 21:51:15 +02:00
|
|
|
pTempIndexes[nTempIndexes] = nPos;
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
// pParamTD will be released at reconversion
|
2011-01-29 01:40:06 +02:00
|
|
|
ppTempParamTD[nTempIndexes++] = pParamTD;
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
2011-01-27 15:44:09 +02:00
|
|
|
//
|
2011-01-31 01:08:29 +02:00
|
|
|
else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTD ) )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
|
|
|
::uno_copyAndConvertData(
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
pUnoArgs[nPos] = alloca( pParamTD->nSize ),
|
|
|
|
pCppStack, pParamTD,
|
2011-01-17 03:52:12 +02:00
|
|
|
pThis->getBridge()->getCpp2Uno() );
|
2011-01-27 15:44:09 +02:00
|
|
|
pTempIndexes[nTempIndexes] = nPos; // Has to be reconverted
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
// pParamTD will be released at reconversion
|
2011-01-29 01:40:06 +02:00
|
|
|
ppTempParamTD[nTempIndexes++] = pParamTD;
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
else // direct way
|
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
pUnoArgs[nPos] = pCppStack;
|
|
|
|
// No longer needed
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
TYPELIB_DANGER_RELEASE( pParamTD );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ExceptionHolder
|
|
|
|
uno_Any aUnoExc; // Any will be constructed by callee
|
|
|
|
uno_Any * pUnoExc = &aUnoExc;
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
// invoke UNO dispatch call
|
2011-01-17 03:52:12 +02:00
|
|
|
(*pThis->getUnoI()->pDispatcher)(
|
2011-01-31 01:08:29 +02:00
|
|
|
pThis->getUnoI(), pMemberTD, pUnoReturn, pUnoArgs, &pUnoExc );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
|
|
|
// in case an exception occurred...
|
2011-01-27 15:44:09 +02:00
|
|
|
if ( pUnoExc )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
// Destruct temporary in/inout params
|
|
|
|
while ( nTempIndexes-- )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
int nIndex = pTempIndexes[nTempIndexes];
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
if ( pParams[nIndex].bIn ) // Is in/inout => was constructed
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-29 01:40:06 +02:00
|
|
|
::uno_destructData( pUnoArgs[nIndex], ppTempParamTD[nTempIndexes], 0 );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
2011-01-29 01:40:06 +02:00
|
|
|
TYPELIB_DANGER_RELEASE( ppTempParamTD[nTempIndexes] );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
2011-01-29 01:40:06 +02:00
|
|
|
if ( pReturnTD )
|
|
|
|
TYPELIB_DANGER_RELEASE( pReturnTD );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
|
|
|
CPPU_CURRENT_NAMESPACE::mscx_raiseException(
|
2011-01-27 15:44:09 +02:00
|
|
|
&aUnoExc, pThis->getBridge()->getUno2Cpp() ); // Has to destruct the any
|
|
|
|
|
|
|
|
// Is here for dummy
|
2011-01-17 03:52:12 +02:00
|
|
|
return typelib_TypeClass_VOID;
|
|
|
|
}
|
2011-01-27 15:44:09 +02:00
|
|
|
else // Else, no exception occurred...
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
// Temporary params
|
2011-01-26 21:51:15 +02:00
|
|
|
while (nTempIndexes--)
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
int nIndex = pTempIndexes[nTempIndexes];
|
2011-01-29 01:40:06 +02:00
|
|
|
typelib_TypeDescription * pParamTD = ppTempParamTD[nTempIndexes];
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
if ( pParams[nIndex].bOut ) // inout/out
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
// Convert and assign
|
2011-01-17 03:52:12 +02:00
|
|
|
::uno_destructData(
|
2011-01-29 01:40:06 +02:00
|
|
|
pCppArgs[nIndex], pParamTD, cpp_release );
|
2011-01-17 03:52:12 +02:00
|
|
|
::uno_copyAndConvertData(
|
2011-01-29 01:40:06 +02:00
|
|
|
pCppArgs[nIndex], pUnoArgs[nIndex], pParamTD,
|
2011-01-17 03:52:12 +02:00
|
|
|
pThis->getBridge()->getUno2Cpp() );
|
|
|
|
}
|
2011-01-31 01:08:29 +02:00
|
|
|
// Destroy temp UNO param
|
2011-01-29 01:40:06 +02:00
|
|
|
::uno_destructData( pUnoArgs[nIndex], pParamTD, 0 );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-29 01:40:06 +02:00
|
|
|
TYPELIB_DANGER_RELEASE( pParamTD );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
2011-01-27 15:44:09 +02:00
|
|
|
// Return
|
|
|
|
if ( pCppReturn ) // Has complex return
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
if ( pUnoReturn != pCppReturn ) // Needs reconversion
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
|
|
|
::uno_copyAndConvertData(
|
2011-01-29 01:40:06 +02:00
|
|
|
pCppReturn, pUnoReturn, pReturnTD,
|
2011-01-17 03:52:12 +02:00
|
|
|
pThis->getBridge()->getUno2Cpp() );
|
2011-01-31 01:08:29 +02:00
|
|
|
// Destroy temp UNO return
|
2011-01-29 01:40:06 +02:00
|
|
|
::uno_destructData( pUnoReturn, pReturnTD, 0 );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
2011-01-27 15:44:09 +02:00
|
|
|
// Complex return ptr is set to eax
|
|
|
|
pStack[0] = pCppReturn;
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
2011-01-29 01:40:06 +02:00
|
|
|
if ( pReturnTD )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-29 01:40:06 +02:00
|
|
|
typelib_TypeClass eRet = (typelib_TypeClass)pReturnTD->eTypeClass;
|
|
|
|
TYPELIB_DANGER_RELEASE( pReturnTD );
|
2011-01-17 03:52:12 +02:00
|
|
|
return eRet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return typelib_TypeClass_VOID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
extern "C" typelib_TypeClass cpp_vtable_call(
|
2011-01-28 18:24:01 +02:00
|
|
|
sal_Int64 nOffsetAndIndex,
|
2011-01-27 15:44:09 +02:00
|
|
|
void ** pStack )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-28 18:24:01 +02:00
|
|
|
sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF);
|
|
|
|
sal_Int32 nVtableOffset = ((nOffsetAndIndex >> 32) & 0xFFFFFFFF);
|
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
// pStack points to space for return value allocated by
|
|
|
|
// privateSnippetExecutor() in call.asm, after which follows our
|
|
|
|
// return address (uninteresting), then the integer or
|
|
|
|
// floating-point register parameters (spilled by
|
|
|
|
// privateSnippetExecutor()) from the call to the trampoline,
|
|
|
|
// followed by stacked parameters. The first parameter is the
|
|
|
|
// 'this' pointer. If the callee returns a large value, the
|
|
|
|
// parameter after that is actually a pointer to where the callee
|
|
|
|
// should store its return value.
|
2011-01-27 15:44:09 +02:00
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
void * pThis = static_cast<char *>( pStack[2] ) - nVtableOffset;
|
2011-01-27 15:44:09 +02:00
|
|
|
|
|
|
|
bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
|
|
|
|
bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
typelib_InterfaceTypeDescription * pTD = pCppI->getTypeDescr();
|
2011-01-27 15:44:09 +02:00
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
OSL_ENSURE( nFunctionIndex < pTD->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
|
|
|
|
if ( nFunctionIndex >= pTD->nMapFunctionIndexToMemberIndex )
|
|
|
|
throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Illegal vtable index!")),
|
2011-01-27 15:44:09 +02:00
|
|
|
reinterpret_cast<XInterface *>( pCppI ) );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
// Determine called method
|
|
|
|
int nMemberPos = pTD->pMapFunctionIndexToMemberIndex[nFunctionIndex];
|
|
|
|
OSL_ENSURE( nMemberPos < pTD->nAllMembers, "### illegal member index!\n" );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
TypeDescription aMemberDescr( pTD->ppAllMembers[nMemberPos] );
|
2011-01-17 03:52:12 +02:00
|
|
|
|
|
|
|
typelib_TypeClass eRet;
|
2011-01-27 15:44:09 +02:00
|
|
|
switch ( aMemberDescr.get()->eTypeClass )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
typelib_TypeDescriptionReference *pAttrTypeRef =
|
|
|
|
reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
|
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
if ( pTD->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
|
2011-01-27 15:44:09 +02:00
|
|
|
{
|
|
|
|
// is GET method
|
|
|
|
eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
|
2011-01-31 01:08:29 +02:00
|
|
|
0, NULL, // No params
|
2011-01-27 15:44:09 +02:00
|
|
|
pStack );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// is SET method
|
|
|
|
typelib_MethodParameter aParam;
|
|
|
|
aParam.pTypeRef = pAttrTypeRef;
|
|
|
|
aParam.bIn = sal_True;
|
|
|
|
aParam.bOut = sal_False;
|
|
|
|
|
|
|
|
eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
|
2011-01-31 01:08:29 +02:00
|
|
|
NULL, // Indicates void return
|
2011-01-27 15:44:09 +02:00
|
|
|
1, &aParam,
|
|
|
|
pStack );
|
|
|
|
}
|
2011-01-17 03:52:12 +02:00
|
|
|
break;
|
2011-01-27 15:44:09 +02:00
|
|
|
}
|
|
|
|
case typelib_TypeClass_INTERFACE_METHOD:
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
// is METHOD
|
|
|
|
switch ( nFunctionIndex )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-27 15:44:09 +02:00
|
|
|
case 1: // acquire()
|
2011-01-31 01:08:29 +02:00
|
|
|
pCppI->acquireProxy(); // Non virtual call!
|
2011-01-27 15:44:09 +02:00
|
|
|
eRet = typelib_TypeClass_VOID;
|
|
|
|
break;
|
|
|
|
case 2: // release()
|
|
|
|
pCppI->releaseProxy(); // non virtual call!
|
|
|
|
eRet = typelib_TypeClass_VOID;
|
2011-01-17 03:52:12 +02:00
|
|
|
break;
|
2011-01-27 15:44:09 +02:00
|
|
|
case 0: // queryInterface() opt
|
|
|
|
{
|
|
|
|
typelib_TypeDescription * pTD = NULL;
|
2011-01-31 01:08:29 +02:00
|
|
|
|
|
|
|
// the incoming C++ parameters are: The this
|
|
|
|
// pointer, the hidden return value pointer, and
|
|
|
|
// then the actual queryInterface() only
|
|
|
|
// parameter. Thus pStack[4]..
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pStack[4] )->getTypeLibType() );
|
|
|
|
|
|
|
|
if ( pTD )
|
|
|
|
{
|
|
|
|
XInterface * pInterface = NULL;
|
|
|
|
(*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
|
|
|
|
( pCppI->getBridge()->getCppEnv(),
|
|
|
|
(void **)&pInterface,
|
|
|
|
pCppI->getOid().pData,
|
|
|
|
reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
|
|
|
|
|
|
|
|
if ( pInterface )
|
|
|
|
{
|
2011-01-31 09:29:55 +02:00
|
|
|
// pStack[3] = hidden return value pointer
|
|
|
|
::uno_any_construct( reinterpret_cast<uno_Any *>( pStack[3] ),
|
2011-01-27 15:44:09 +02:00
|
|
|
&pInterface, pTD, cpp_acquire );
|
|
|
|
|
|
|
|
pInterface->release();
|
|
|
|
TYPELIB_DANGER_RELEASE( pTD );
|
|
|
|
|
|
|
|
eRet = typelib_TypeClass_ANY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
TYPELIB_DANGER_RELEASE( pTD );
|
|
|
|
}
|
|
|
|
} // Fall through!
|
|
|
|
default:
|
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
typelib_InterfaceMethodTypeDescription * pMethodTD =
|
2011-01-27 15:44:09 +02:00
|
|
|
reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
|
|
|
|
|
|
|
|
eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
|
|
|
|
pMethodTD->pReturnTypeRef,
|
|
|
|
pMethodTD->nParams,
|
|
|
|
pMethodTD->pParams,
|
|
|
|
pStack );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
}
|
2011-01-27 15:44:09 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-01-17 03:52:12 +02:00
|
|
|
default:
|
2011-01-27 15:44:09 +02:00
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No member description found!")),
|
2011-01-27 15:44:09 +02:00
|
|
|
reinterpret_cast<XInterface *>( pCppI ) );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return eRet;
|
|
|
|
}
|
|
|
|
|
2011-01-28 18:24:01 +02:00
|
|
|
int const codeSnippetSize = 48;
|
|
|
|
|
|
|
|
extern "C" char privateSnippetExecutor;
|
2011-01-17 03:52:12 +02:00
|
|
|
|
2011-01-26 21:51:15 +02:00
|
|
|
// This function generates the code that acts as a proxy for the UNO function to be called.
|
|
|
|
// The generated code does the following:
|
2011-01-28 18:24:01 +02:00
|
|
|
// - Spills register parameters on stack
|
|
|
|
// - Loads functionIndex and vtableOffset into scratch registers
|
|
|
|
// - Jumps to privateSnippetExecutor
|
2011-01-22 03:20:19 +02:00
|
|
|
|
2011-01-17 03:52:12 +02:00
|
|
|
unsigned char * codeSnippet(
|
2011-01-27 15:44:09 +02:00
|
|
|
unsigned char * code,
|
|
|
|
char param_kind[4],
|
2011-01-28 18:24:01 +02:00
|
|
|
sal_Int32 nFunctionIndex,
|
2011-01-31 01:08:29 +02:00
|
|
|
sal_Int32 nVtableOffset )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
2011-01-28 18:24:01 +02:00
|
|
|
sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex );
|
|
|
|
unsigned char *p = code;
|
2011-01-26 21:51:15 +02:00
|
|
|
|
2011-01-28 18:24:01 +02:00
|
|
|
// Spill parameters
|
|
|
|
if ( param_kind[0] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
{
|
2011-01-28 18:24:01 +02:00
|
|
|
// 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;
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
}
|
2011-01-28 18:24:01 +02:00
|
|
|
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;
|
2011-01-27 15:44:09 +02:00
|
|
|
|
2011-01-28 18:24:01 +02:00
|
|
|
OSL_ASSERT( p < code + codeSnippetSize );
|
2011-01-27 15:44:09 +02:00
|
|
|
|
|
|
|
return code + codeSnippetSize;
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
|
|
|
|
|
|
|
|
bridges::cpp_uno::shared::VtableFactory::Slot *
|
2011-01-31 01:08:29 +02:00
|
|
|
bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(
|
|
|
|
void * block )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
|
|
|
return static_cast< Slot * >(block) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
|
2011-01-31 01:08:29 +02:00
|
|
|
sal_Int32 slotCount )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
|
|
|
return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
bridges::cpp_uno::shared::VtableFactory::Slot *
|
|
|
|
bridges::cpp_uno::shared::VtableFactory::initializeBlock(
|
2011-01-31 01:08:29 +02:00
|
|
|
void * block,
|
|
|
|
sal_Int32 slotCount )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
|
|
|
struct Rtti {
|
|
|
|
sal_Int32 n0, n1, n2;
|
|
|
|
type_info * rtti;
|
|
|
|
Rtti():
|
|
|
|
n0(0), n1(0), n2(0),
|
|
|
|
rtti(CPPU_CURRENT_NAMESPACE::mscx_getRTTI(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"com.sun.star.uno.XInterface"))))
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
static Rtti rtti;
|
|
|
|
|
|
|
|
Slot * slots = mapBlockToVtable(block);
|
|
|
|
slots[-1].fn = &rtti;
|
|
|
|
return slots + slotCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
|
2011-01-31 01:08:29 +02:00
|
|
|
Slot ** slots,
|
|
|
|
unsigned char * code,
|
|
|
|
typelib_InterfaceTypeDescription const * type,
|
|
|
|
sal_Int32 nFunctionOffset,
|
|
|
|
sal_Int32 functionCount,
|
|
|
|
sal_Int32 nVtableOffset )
|
2011-01-17 03:52:12 +02:00
|
|
|
{
|
|
|
|
(*slots) -= functionCount;
|
|
|
|
Slot * s = *slots;
|
2011-01-26 21:51:15 +02:00
|
|
|
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
for (int member = 0; member < type->nMembers; ++member) {
|
|
|
|
typelib_TypeDescription * pTD = NULL;
|
2011-01-26 21:51:15 +02:00
|
|
|
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
TYPELIB_DANGER_GET( &pTD, type->ppMembers[ member ] );
|
2011-01-26 21:51:15 +02:00
|
|
|
OSL_ASSERT( pTD );
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
char param_kind[4];
|
2011-01-26 21:51:15 +02:00
|
|
|
int nr = 0;
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
param_kind[i] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT;
|
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
// 'this'
|
|
|
|
++nr;
|
|
|
|
|
2011-01-26 21:51:15 +02:00
|
|
|
if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE )
|
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
typelib_InterfaceAttributeTypeDescription * pIfaceAttrTD =
|
2011-01-26 21:51:15 +02:00
|
|
|
reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
// Getter
|
|
|
|
|
2011-01-26 21:51:15 +02:00
|
|
|
(s++)->fn = code;
|
2011-01-31 01:08:29 +02:00
|
|
|
code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
|
|
|
|
if ( ! pIfaceAttrTD->bReadOnly )
|
2011-01-26 21:51:15 +02:00
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
typelib_TypeDescription * pAttrTD = NULL;
|
|
|
|
TYPELIB_DANGER_GET( &pAttrTD, pIfaceAttrTD->pAttributeTypeRef );
|
|
|
|
OSL_ASSERT( pAttrTD );
|
|
|
|
|
2011-01-27 15:44:09 +02:00
|
|
|
// Setter
|
2011-01-31 01:08:29 +02:00
|
|
|
if ( pAttrTD->eTypeClass == typelib_TypeClass_FLOAT ||
|
|
|
|
pAttrTD->eTypeClass == typelib_TypeClass_DOUBLE )
|
|
|
|
param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT;
|
|
|
|
|
|
|
|
TYPELIB_DANGER_RELEASE( pAttrTD );
|
|
|
|
|
2011-01-26 21:51:15 +02:00
|
|
|
(s++)->fn = code;
|
2011-01-31 01:08:29 +02:00
|
|
|
code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
|
2011-01-26 21:51:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_METHOD )
|
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
typelib_InterfaceMethodTypeDescription * pMethodTD =
|
2011-01-26 21:51:15 +02:00
|
|
|
reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
|
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
typelib_TypeDescription * pReturnTD = NULL;
|
2011-01-26 21:51:15 +02:00
|
|
|
TYPELIB_DANGER_GET( &pReturnTD, pMethodTD->pReturnTypeRef );
|
|
|
|
OSL_ASSERT( pReturnTD );
|
|
|
|
|
2011-01-31 01:08:29 +02:00
|
|
|
if ( !bridges::cpp_uno::shared::isSimpleType( pReturnTD ) )
|
2011-01-27 15:44:09 +02:00
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
// Return value
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
++nr;
|
2011-01-26 21:51:15 +02:00
|
|
|
}
|
|
|
|
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
for (int param = 0; nr < 4 && param < pMethodTD->nParams; ++param, ++nr)
|
2011-01-26 21:51:15 +02:00
|
|
|
{
|
2011-01-31 01:08:29 +02:00
|
|
|
typelib_TypeDescription * pParamTD = NULL;
|
2011-01-26 21:51:15 +02:00
|
|
|
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
TYPELIB_DANGER_GET( &pParamTD, pMethodTD->pParams[param].pTypeRef );
|
2011-01-26 21:51:15 +02:00
|
|
|
OSL_ASSERT( pParamTD );
|
|
|
|
|
|
|
|
if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT ||
|
|
|
|
pParamTD->eTypeClass == typelib_TypeClass_DOUBLE )
|
More work on x64 Windows C++-UNO bridge
Now the call through the trampoline into cpp_vtable_call() seems to
work, but I get a crash later. Glitches in parameter passing, no
doubt. Debugging needed in cpp_vtable_call() and cpp2uno_call().
The basic implementation is probably sane. But I wonder if I after all
should have done like in the x86-64 Linux implementation, with the
dynamically generated trampoline just jumping into fixed code shared
between all trampolines. Probably should redo it like that, yes.
Will it then cause a problem for OS unwinding if the caller of the
trampoline calls a short dynamically generated code snippet, which
then jumps into the fixed part, and only the fixed part has a
(assembler-generated) function table and unwind info? Probably not.
It is quite impossible that such a short dynamically generated snippet
with just a couple of instructions would cause an exception, and when
we have jumped into the fixed part, where the call to
cpp_vtable_call() is done, it doesn't matter any more that the caller
in fact didn't call what the function table claims is the entry
point. Or does it?
Doing it that way would mean no RtlAddFunctionTable() and
RtlDeleteFunctionTable() would be needed, and especially doing the
latter correctly is a bit hairy.
2011-01-28 16:30:54 +02:00
|
|
|
param_kind[nr] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT;
|
2011-01-26 21:51:15 +02:00
|
|
|
|
|
|
|
TYPELIB_DANGER_RELEASE( pParamTD );
|
2011-01-27 15:44:09 +02:00
|
|
|
}
|
|
|
|
(s++)->fn = code;
|
2011-01-31 01:08:29 +02:00
|
|
|
code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
|
2011-01-27 15:44:09 +02:00
|
|
|
|
|
|
|
TYPELIB_DANGER_RELEASE( pReturnTD );
|
2011-01-26 21:51:15 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
OSL_ASSERT( false );
|
2011-01-27 15:44:09 +02:00
|
|
|
|
|
|
|
TYPELIB_DANGER_RELEASE( pTD );
|
2011-01-17 03:52:12 +02:00
|
|
|
}
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bridges::cpp_uno::shared::VtableFactory::flushCode(
|
2011-01-31 01:08:29 +02:00
|
|
|
unsigned char const *,
|
|
|
|
unsigned char const * )
|
|
|
|
{
|
|
|
|
}
|
2011-01-17 03:52:12 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|