INTEGRATION: CWS pj16 (1.3.158); FILE MERGED

2005/01/14 17:57:36 pjanik 1.3.158.1: #i40178#: FreeBSD porting: catch up recent version of
bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx

From NAKATA Maho.
This commit is contained in:
Kurt Zenker 2005-01-18 14:06:09 +00:00
parent 3e5a9c073d
commit 56c0add9db

View file

@ -2,9 +2,9 @@
* *
* $RCSfile: cpp2uno.cxx,v $ * $RCSfile: cpp2uno.cxx,v $
* *
* $Revision: 1.3 $ * $Revision: 1.4 $
* *
* last change: $Author: hr $ $Date: 2003-04-28 16:28:20 $ * last change: $Author: kz $ $Date: 2005-01-18 15:06:09 $
* *
* The Contents of this file are made available subject to the terms of * The Contents of this file are made available subject to the terms of
* either of the following licenses * either of the following licenses
@ -59,34 +59,26 @@
* *
************************************************************************/ ************************************************************************/
#include <hash_map> #include <com/sun/star/uno/genfunc.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"
#include <sal/alloca.h>
#include <rtl/alloc.h>
#include <osl/mutex.hxx>
#include <uno/data.h> #include <uno/data.h>
#include <typelib/typedescription.hxx> #include <typelib/typedescription.hxx>
#include <bridges/cpp_uno/bridge.hxx> #include "bridges/cpp_uno/shared/bridge.hxx"
#include <bridges/cpp_uno/type_misc.hxx> #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
#include "bridges/cpp_uno/shared/types.hxx"
#include "bridges/cpp_uno/shared/vtablefactory.hxx"
#include "share.hxx" #include "share.hxx"
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno; using namespace ::com::sun::star::uno;
namespace CPPU_CURRENT_NAMESPACE namespace
{ {
//==================================================================================================
rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
//================================================================================================== //==================================================================================================
static typelib_TypeClass cpp2uno_call( static typelib_TypeClass cpp2uno_call(
cppu_cppInterfaceProxy * pThis, bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
const typelib_TypeDescription * pMemberTypeDescr, const typelib_TypeDescription * pMemberTypeDescr,
typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
sal_Int32 nParams, typelib_MethodParameter * pParams, sal_Int32 nParams, typelib_MethodParameter * pParams,
@ -106,7 +98,7 @@ static typelib_TypeClass cpp2uno_call(
if (pReturnTypeDescr) if (pReturnTypeDescr)
{ {
if (cppu_isSimpleType( pReturnTypeDescr )) if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
{ {
pUnoReturn = pRegisterReturn; // direct way for simple types pUnoReturn = pRegisterReturn; // direct way for simple types
} }
@ -115,7 +107,8 @@ static typelib_TypeClass cpp2uno_call(
pCppReturn = *(void **)pCppStack; pCppReturn = *(void **)pCppStack;
pCppStack += sizeof(void *); pCppStack += sizeof(void *);
pUnoReturn = (cppu_relatesToInterface( pReturnTypeDescr ) pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
pReturnTypeDescr )
? alloca( pReturnTypeDescr->nSize ) ? alloca( pReturnTypeDescr->nSize )
: pCppReturn); // direct way : pCppReturn); // direct way
} }
@ -141,7 +134,9 @@ static typelib_TypeClass cpp2uno_call(
typelib_TypeDescription * pParamTypeDescr = 0; typelib_TypeDescription * pParamTypeDescr = 0;
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
if (!rParam.bOut && cppu_isSimpleType( pParamTypeDescr )) // value if (!rParam.bOut
&& bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
// value
{ {
pCppArgs[nPos] = pCppStack; pCppArgs[nPos] = pCppStack;
pUnoArgs[nPos] = pCppStack; pUnoArgs[nPos] = pCppStack;
@ -168,11 +163,12 @@ static typelib_TypeClass cpp2uno_call(
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
} }
// is in/inout // is in/inout
else if (cppu_relatesToInterface( pParamTypeDescr )) else if (bridges::cpp_uno::shared::relatesToInterfaceType(
pParamTypeDescr ))
{ {
uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
*(void **)pCppStack, pParamTypeDescr, *(void **)pCppStack, pParamTypeDescr,
&pThis->pBridge->aCpp2Uno ); pThis->getBridge()->getCpp2Uno() );
pTempIndizes[nTempIndizes] = nPos; // has to be reconverted pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
// will be released at reconversion // will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
@ -192,7 +188,8 @@ static typelib_TypeClass cpp2uno_call(
uno_Any * pUnoExc = &aUnoExc; uno_Any * pUnoExc = &aUnoExc;
// invoke uno dispatch call // invoke uno dispatch call
(*pThis->pUnoI->pDispatcher)( pThis->pUnoI, pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); (*pThis->getUnoI()->pDispatcher)(
pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
// in case an exception occured... // in case an exception occured...
if (pUnoExc) if (pUnoExc)
@ -209,7 +206,9 @@ static typelib_TypeClass cpp2uno_call(
if (pReturnTypeDescr) if (pReturnTypeDescr)
TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
raiseException( &aUnoExc, &pThis->pBridge->aUno2Cpp ); // has to destruct the any CPPU_CURRENT_NAMESPACE::raiseException(
&aUnoExc, pThis->getBridge()->getUno2Cpp() );
// has to destruct the any
// is here for dummy // is here for dummy
return typelib_TypeClass_VOID; return typelib_TypeClass_VOID;
} }
@ -226,7 +225,7 @@ static typelib_TypeClass cpp2uno_call(
// convert and assign // convert and assign
uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
&pThis->pBridge->aUno2Cpp ); pThis->getBridge()->getUno2Cpp() );
} }
// destroy temp uno param // destroy temp uno param
uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
@ -239,7 +238,7 @@ static typelib_TypeClass cpp2uno_call(
if (pUnoReturn != pCppReturn) // needs reconversion if (pUnoReturn != pCppReturn) // needs reconversion
{ {
uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
&pThis->pBridge->aUno2Cpp ); pThis->getBridge()->getUno2Cpp() );
// destroy temp uno return // destroy temp uno return
uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
} }
@ -260,38 +259,41 @@ static typelib_TypeClass cpp2uno_call(
//================================================================================================== //==================================================================================================
static typelib_TypeClass cpp_mediate( static typelib_TypeClass cpp_mediate(
sal_Int32 nVtableCall, sal_Int32 nFunctionIndex,
sal_Int32 nVtableOffset,
void ** pCallStack, void ** pCallStack,
sal_Int64 * pRegisterReturn /* space for register return */ ) sal_Int64 * pRegisterReturn /* space for register return */ )
{ {
OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
// pCallStack: ret adr, [ret *], this, params // pCallStack: ret adr, [ret *], this, params
// _this_ ptr is patched cppu_XInterfaceProxy object void * pThis;
cppu_cppInterfaceProxy * pCppI = NULL; if( nFunctionIndex & 0x80000000 )
if( nVtableCall & 0x80000000 )
{ {
nVtableCall &= 0x7fffffff; nFunctionIndex &= 0x7fffffff;
pCppI = (cppu_cppInterfaceProxy *)(XInterface *)*(pCallStack +2); pThis = pCallStack[2];
} }
else else
{ {
pCppI = (cppu_cppInterfaceProxy *)(XInterface *)*(pCallStack +1); pThis = pCallStack[1];
} }
pThis = static_cast< char * >(pThis) - nVtableOffset;
bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
= bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
pThis);
typelib_InterfaceTypeDescription * pTypeDescr = pCppI->pTypeDescr; typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
if (nVtableCall >= pTypeDescr->nMapFunctionIndexToMemberIndex) if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
{ {
throw RuntimeException( throw RuntimeException(
OUString::createFromAscii("illegal vtable index!"), rtl::OUString::createFromAscii("illegal vtable index!"),
(XInterface *)pCppI ); (XInterface *)pThis );
} }
// determine called method // determine called method
OSL_ENSURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nVtableCall];
OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
@ -301,7 +303,7 @@ static typelib_TypeClass cpp_mediate(
{ {
case typelib_TypeClass_INTERFACE_ATTRIBUTE: case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{ {
if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nVtableCall) if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
{ {
// is GET method // is GET method
eRet = cpp2uno_call( eRet = cpp2uno_call(
@ -330,7 +332,7 @@ static typelib_TypeClass cpp_mediate(
case typelib_TypeClass_INTERFACE_METHOD: case typelib_TypeClass_INTERFACE_METHOD:
{ {
// is METHOD // is METHOD
switch (nVtableCall) switch (nFunctionIndex)
{ {
case 1: // acquire() case 1: // acquire()
pCppI->acquireProxy(); // non virtual call! pCppI->acquireProxy(); // non virtual call!
@ -347,9 +349,10 @@ static typelib_TypeClass cpp_mediate(
if (pTD) if (pTD)
{ {
XInterface * pInterface = 0; XInterface * pInterface = 0;
(*pCppI->pBridge->pCppEnv->getRegisteredInterface)( (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
pCppI->pBridge->pCppEnv, pCppI->getBridge()->getCppEnv(),
(void **)&pInterface, pCppI->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); (void **)&pInterface, pCppI->getOid().pData,
(typelib_InterfaceTypeDescription *)pTD );
if (pInterface) if (pInterface)
{ {
@ -378,8 +381,8 @@ static typelib_TypeClass cpp_mediate(
default: default:
{ {
throw RuntimeException( throw RuntimeException(
OUString::createFromAscii("no member description found!"), rtl::OUString::createFromAscii("no member description found!"),
(XInterface *)pCppI ); (XInterface *)pThis );
// is here for dummy // is here for dummy
eRet = typelib_TypeClass_VOID; eRet = typelib_TypeClass_VOID;
} }
@ -393,12 +396,15 @@ static typelib_TypeClass cpp_mediate(
* is called on incoming vtable calls * is called on incoming vtable calls
* (called by asm snippets) * (called by asm snippets)
*/ */
static void cpp_vtable_call( int nTableEntry, void** pCallStack ) __attribute__((regparm(2))); static void cpp_vtable_call(
int nFunctionIndex, int nVtableOffset, void** pCallStack )
__attribute__((regparm(3)));
void cpp_vtable_call( int nTableEntry, void** pCallStack ) void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** pCallStack )
{ {
volatile long nRegReturn[2]; volatile long nRegReturn[2];
typelib_TypeClass aType = cpp_mediate( nTableEntry, pCallStack, (sal_Int64*)nRegReturn ); typelib_TypeClass aType = cpp_mediate(
nFunctionIndex, nVtableOffset, pCallStack, (sal_Int64*)nRegReturn );
switch( aType ) switch( aType )
{ {
@ -434,161 +440,103 @@ void cpp_vtable_call( int nTableEntry, void** pCallStack )
//================================================================================================== //==================================================================================================
class MediateClassData int const codeSnippetSize = 20;
unsigned char * codeSnippet(
unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
bool simpleRetType)
{ {
typedef ::std::hash_map< OUString, void *, OUStringHash > t_classdata_map; if (!simpleRetType) {
t_classdata_map m_map; functionIndex |= 0x80000000;
Mutex m_mutex;
public:
void const * get_vtable( typelib_InterfaceTypeDescription * pTD ) SAL_THROW( () );
inline MediateClassData() SAL_THROW( () )
{}
~MediateClassData() SAL_THROW( () );
};
//__________________________________________________________________________________________________
MediateClassData::~MediateClassData() SAL_THROW( () )
{
OSL_TRACE( "> calling ~MediateClassData(): freeing mediate vtables." );
for ( t_classdata_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos )
{
::rtl_freeMemory( iPos->second );
} }
unsigned char * p = code;
OSL_ASSERT(sizeof (sal_Int32) == 4);
// mov function_index, %eax:
*p++ = 0xB8;
*reinterpret_cast< sal_Int32 * >(p) = functionIndex;
p += sizeof (sal_Int32);
// mov vtable_offset, %edx:
*p++ = 0xBA;
*reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
p += sizeof (sal_Int32);
// mov %esp, %ecx:
*p++ = 0x89;
*p++ = 0xE1;
// jmp cpp_vtable_call:
*p++ = 0xE9;
*reinterpret_cast< sal_Int32 * >(p)
= ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32);
p += sizeof (sal_Int32);
OSL_ASSERT(p - code <= codeSnippetSize);
return code + codeSnippetSize;
} }
//--------------------------------------------------------------------------------------------------
static inline void codeSnippet( char * code, sal_uInt32 vtable_pos, bool simple_ret_type ) SAL_THROW( () )
{
if (! simple_ret_type)
vtable_pos |= 0x80000000;
OSL_ASSERT( sizeof (long) == 4 );
// mov $nPos, %eax
*code++ = 0xb8;
*(long *)code = vtable_pos;
code += sizeof (long);
// mov %esp, %edx
*code++ = 0x89;
*code++ = 0xe2;
// jmp cpp_vtable_call
*code++ = 0xe9;
*(long *)code = ((char *)cpp_vtable_call) - code - sizeof (long);
} }
//__________________________________________________________________________________________________
void const * MediateClassData::get_vtable( typelib_InterfaceTypeDescription * pTD ) SAL_THROW( () ) void ** bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(char * block)
{ {
void * buffer; return reinterpret_cast< void ** >(block) + 2;
}
// avoiding locked counts char * bridges::cpp_uno::shared::VtableFactory::createBlock(
OUString const & unoName = *(OUString const *)&((typelib_TypeDescription *)pTD)->pTypeName; sal_Int32 slotCount, void *** slots)
{ {
MutexGuard aGuard( m_mutex ); char * block = new char[
t_classdata_map::const_iterator iFind( m_map.find( unoName ) ); (slotCount + 2) * sizeof (void *) + slotCount * codeSnippetSize];
if (iFind == m_map.end()) *slots = mapBlockToVtable(block);
{ (*slots)[-2] = 0;
// create new vtable (*slots)[-1] = 0;
sal_Int32 nSlots = pTD->nMapFunctionIndexToMemberIndex; return block;
buffer = ::rtl_allocateMemory( ((2+ nSlots) * sizeof (void *)) + (nSlots *20) ); }
::std::pair< t_classdata_map::iterator, bool > insertion( unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
m_map.insert( t_classdata_map::value_type( unoName, buffer ) ) ); void ** slots, unsigned char * code,
OSL_ENSURE( insertion.second, "### inserting new vtable buffer failed?!" ); typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
sal_Int32 functionCount, sal_Int32 vtableOffset)
void ** slots = (void **)buffer; {
*slots++ = 0; for (sal_Int32 i = 0; i < type->nMembers; ++i) {
*slots++ = 0; // rtti typelib_TypeDescription * member = 0;
char * code = (char *)(slots + nSlots); TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
OSL_ASSERT(member != 0);
sal_uInt32 vtable_pos = 0; switch (member->eTypeClass) {
sal_Int32 nAllMembers = pTD->nAllMembers; case typelib_TypeClass_INTERFACE_ATTRIBUTE:
typelib_TypeDescriptionReference ** ppAllMembers = pTD->ppAllMembers; // Getter:
for ( sal_Int32 nPos = 0; nPos < nAllMembers; ++nPos ) *slots++ = code;
{ code = codeSnippet(
typelib_TypeDescription * pTD = 0; code, functionOffset++, vtableOffset,
TYPELIB_DANGER_GET( &pTD, ppAllMembers[ nPos ] ); bridges::cpp_uno::shared::isSimpleType(
OSL_ASSERT( pTD ); reinterpret_cast<
if (typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass) typelib_InterfaceAttributeTypeDescription * >(
member)->pAttributeTypeRef));
// Setter:
if (!reinterpret_cast<
typelib_InterfaceAttributeTypeDescription * >(
member)->bReadOnly)
{ {
bool simple_ret = cppu_isSimpleType(
((typelib_InterfaceAttributeTypeDescription *)pTD)->pAttributeTypeRef->eTypeClass );
// get method
*slots++ = code; *slots++ = code;
codeSnippet( code, vtable_pos++, simple_ret ); code = codeSnippet(code, functionOffset++, vtableOffset, true);
code += 20;
if (! ((typelib_InterfaceAttributeTypeDescription *)pTD)->bReadOnly)
{
// set method
*slots++ = code;
codeSnippet( code, vtable_pos++, true );
code += 20;
}
} }
else break;
{
bool simple_ret = cppu_isSimpleType( case typelib_TypeClass_INTERFACE_METHOD:
((typelib_InterfaceMethodTypeDescription *)pTD)->pReturnTypeRef->eTypeClass ); *slots++ = code;
*slots++ = code; code = codeSnippet(
codeSnippet( code, vtable_pos++, simple_ret ); code, functionOffset++, vtableOffset,
code += 20; bridges::cpp_uno::shared::isSimpleType(
} reinterpret_cast<
TYPELIB_DANGER_RELEASE( pTD ); typelib_InterfaceMethodTypeDescription * >(
member)->pReturnTypeRef));
break;
default:
OSL_ASSERT(false);
break;
} }
OSL_ASSERT( vtable_pos == nSlots ); TYPELIB_DANGER_RELEASE(member);
} }
else return code;
{
buffer = iFind->second;
}
}
return ((void **)buffer +2);
} }
//================================================================================================== void bridges::cpp_uno::shared::VtableFactory::flushCode(
void SAL_CALL cppu_cppInterfaceProxy_patchVtable( unsigned char const *, unsigned char const *)
XInterface * pCppI, typelib_InterfaceTypeDescription * pTypeDescr ) throw () {}
{
static MediateClassData * s_pMediateClassData = 0;
if (! s_pMediateClassData)
{
MutexGuard aGuard( Mutex::getGlobalMutex() );
if (! s_pMediateClassData)
{
#ifdef LEAK_STATIC_DATA
s_pMediateClassData = new MediateClassData();
#else
static MediateClassData s_aMediateClassData;
s_pMediateClassData = &s_aMediateClassData;
#endif
}
}
*(void const **)pCppI = s_pMediateClassData->get_vtable( pTypeDescr );
}
}
extern "C"
{
//##################################################################################################
sal_Bool SAL_CALL component_canUnload( TimeValue * pTime )
SAL_THROW_EXTERN_C()
{
return CPPU_CURRENT_NAMESPACE::g_moduleCount.canUnload(
&CPPU_CURRENT_NAMESPACE::g_moduleCount, pTime );
}
//##################################################################################################
void SAL_CALL uno_initEnvironment( uno_Environment * pCppEnv )
SAL_THROW_EXTERN_C()
{
CPPU_CURRENT_NAMESPACE::cppu_cppenv_initEnvironment(
pCppEnv );
}
//##################################################################################################
void SAL_CALL uno_ext_getMapping(
uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
SAL_THROW_EXTERN_C()
{
CPPU_CURRENT_NAMESPACE::cppu_ext_getMapping(
ppMapping, pFrom, pTo );
}
}