1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "precompiled_bridges.hxx" 29 #include "sal/config.h" 30 31 #include <cstddef> 32 #include <cstdlib> 33 #include <cstring> 34 35 #include "bridges/cpp_uno/shared/bridge.hxx" 36 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 37 #include "bridges/cpp_uno/shared/types.hxx" 38 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 39 #include "com/sun/star/uno/genfunc.hxx" 40 #include "osl/diagnose.h" 41 #include "sal/alloca.h" 42 #include "sal/types.h" 43 #include "typelib/typeclass.h" 44 #include "typelib/typedescription.h" 45 #include "typelib/typedescription.hxx" 46 #include "uno/any2.h" 47 #include "uno/data.h" 48 49 #include "exceptions.hxx" 50 #include "flushcode.hxx" 51 #include "fp.hxx" 52 #include "isdirectreturntype.hxx" 53 #include "vtableslotcall.hxx" 54 55 namespace { 56 57 namespace css = com::sun::star; 58 59 void loadFpRegsFromStruct(typelib_TypeDescription * type, void * data) { 60 for (typelib_CompoundTypeDescription * t = 61 reinterpret_cast< typelib_CompoundTypeDescription * >(type); 62 t != NULL; t = t->pBaseTypeDescription) 63 { 64 for (sal_Int32 i = 0; i < t->nMembers; ++i) { 65 switch (t->ppTypeRefs[i]->eTypeClass) { 66 case typelib_TypeClass_FLOAT: 67 switch (t->pMemberOffsets[i]) { 68 case 0: 69 fp_loadf0(reinterpret_cast< float * >(data)); 70 break; 71 case 4: 72 fp_loadf1(reinterpret_cast< float * >(data) + 1); 73 break; 74 case 8: 75 fp_loadf2(reinterpret_cast< float * >(data) + 2); 76 break; 77 case 12: 78 fp_loadf3(reinterpret_cast< float * >(data) + 3); 79 break; 80 case 16: 81 fp_loadf4(reinterpret_cast< float * >(data) + 4); 82 break; 83 case 20: 84 fp_loadf5(reinterpret_cast< float * >(data) + 5); 85 break; 86 case 24: 87 fp_loadf6(reinterpret_cast< float * >(data) + 6); 88 break; 89 case 28: 90 fp_loadf7(reinterpret_cast< float * >(data) + 7); 91 break; 92 default: 93 OSL_ASSERT(false); 94 break; 95 } 96 break; 97 case typelib_TypeClass_DOUBLE: 98 switch (t->pMemberOffsets[i]) { 99 case 0: 100 fp_loadd0(reinterpret_cast< double * >(data)); 101 break; 102 case 8: 103 fp_loadd2(reinterpret_cast< double * >(data) + 1); 104 break; 105 case 16: 106 fp_loadd4(reinterpret_cast< double * >(data) + 2); 107 break; 108 case 24: 109 fp_loadd6(reinterpret_cast< double * >(data) + 3); 110 break; 111 default: 112 OSL_ASSERT(false); 113 break; 114 } 115 break; 116 case typelib_TypeClass_STRUCT: 117 { 118 typelib_TypeDescription * td = NULL; 119 TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]); 120 loadFpRegsFromStruct(td, data); 121 TYPELIB_DANGER_RELEASE(td); 122 break; 123 } 124 } 125 } 126 } 127 } 128 129 void call( 130 bridges::cpp_uno::shared::CppInterfaceProxy * proxy, 131 css::uno::TypeDescription const & description, 132 bool directReturn, typelib_TypeDescriptionReference * returnType, 133 sal_Int32 count, typelib_MethodParameter * parameters, 134 unsigned long * callStack) 135 { 136 typelib_TypeDescription * rtd = NULL; 137 if (returnType != NULL) { 138 TYPELIB_DANGER_GET(&rtd, returnType); 139 } 140 bool retconv = 141 rtd != NULL && bridges::cpp_uno::shared::relatesToInterfaceType(rtd); 142 OSL_ASSERT(!(directReturn && retconv)); 143 void * retin; 144 void * retout; 145 char retbuf[32]; 146 if (directReturn) { 147 retin = returnType == NULL ? NULL : retbuf; 148 } else { 149 retout = reinterpret_cast< void * >(callStack[0]); 150 retin = retconv ? alloca(rtd->nSize) : retout; 151 } 152 void ** args = static_cast< void ** >(alloca(count * sizeof (void *))); 153 void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *))); 154 typelib_TypeDescription ** argtds = 155 static_cast< typelib_TypeDescription ** >( 156 alloca(count * sizeof (typelib_TypeDescription *))); 157 union fp { float f; double d; }; 158 fp copies[15]; 159 sal_Int32 stackPos = directReturn ? 1 : 2; // skip return ptr and this ptr 160 for (sal_Int32 i = 0; i < count; ++i) { 161 typelib_TypeDescription * ptd = NULL; 162 TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); 163 if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(ptd)) 164 { 165 switch (ptd->eTypeClass) { 166 case typelib_TypeClass_FLOAT: 167 if (stackPos <= 15) { 168 switch (stackPos) { 169 case 1: 170 fp_storef3(&copies[0].f); 171 break; 172 case 2: 173 fp_storef5(&copies[1].f); 174 break; 175 case 3: 176 fp_storef7(&copies[2].f); 177 break; 178 case 4: 179 fp_storef9(&copies[3].f); 180 break; 181 case 5: 182 fp_storef11(&copies[4].f); 183 break; 184 case 6: 185 fp_storef13(&copies[5].f); 186 break; 187 case 7: 188 fp_storef15(&copies[6].f); 189 break; 190 case 8: 191 fp_storef17(&copies[7].f); 192 break; 193 case 9: 194 fp_storef19(&copies[8].f); 195 break; 196 case 10: 197 fp_storef21(&copies[9].f); 198 break; 199 case 11: 200 fp_storef23(&copies[10].f); 201 break; 202 case 12: 203 fp_storef25(&copies[11].f); 204 break; 205 case 13: 206 fp_storef27(&copies[12].f); 207 break; 208 case 14: 209 fp_storef29(&copies[13].f); 210 break; 211 case 15: 212 fp_storef31(&copies[14].f); 213 break; 214 default: 215 OSL_ASSERT(false); 216 break; 217 } 218 args[i] = &copies[stackPos - 1].f; 219 } else { 220 args[i] = reinterpret_cast< char * >(callStack + stackPos) + 221 (sizeof (unsigned long) - sizeof (float)); 222 } 223 break; 224 case typelib_TypeClass_DOUBLE: 225 if (stackPos <= 15) { 226 switch (stackPos) { 227 case 1: 228 fp_stored2(&copies[0].d); 229 break; 230 case 2: 231 fp_stored4(&copies[1].d); 232 break; 233 case 3: 234 fp_stored6(&copies[2].d); 235 break; 236 case 4: 237 fp_stored8(&copies[3].d); 238 break; 239 case 5: 240 fp_stored10(&copies[4].d); 241 break; 242 case 6: 243 fp_stored12(&copies[5].d); 244 break; 245 case 7: 246 fp_stored14(&copies[6].d); 247 break; 248 case 8: 249 fp_stored16(&copies[7].d); 250 break; 251 case 9: 252 fp_stored18(&copies[8].d); 253 break; 254 case 10: 255 fp_stored20(&copies[9].d); 256 break; 257 case 11: 258 fp_stored22(&copies[10].d); 259 break; 260 case 12: 261 fp_stored24(&copies[11].d); 262 break; 263 case 13: 264 fp_stored26(&copies[12].d); 265 break; 266 case 14: 267 fp_stored28(&copies[13].d); 268 break; 269 case 15: 270 fp_stored30(&copies[14].d); 271 break; 272 default: 273 OSL_ASSERT(false); 274 break; 275 } 276 args[i] = &copies[stackPos - 1].d; 277 } else { 278 args[i] = reinterpret_cast< char * >(callStack + stackPos) + 279 (sizeof (unsigned long) - sizeof (double)); 280 } 281 break; 282 default: 283 OSL_ASSERT(ptd->nSize <= 8); 284 args[i] = reinterpret_cast< char * >(callStack + stackPos) + 285 (sizeof (unsigned long) - ptd->nSize); 286 break; 287 } 288 argtds[i] = NULL; 289 TYPELIB_DANGER_RELEASE(ptd); 290 } else { 291 cppArgs[i] = reinterpret_cast< void * >(callStack[stackPos]); 292 if (!parameters[i].bIn) { 293 args[i] = alloca(ptd->nSize); 294 argtds[i] = ptd; 295 } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) { 296 args[i] = alloca(ptd->nSize); 297 uno_copyAndConvertData( 298 args[i], reinterpret_cast< void * >(callStack[stackPos]), 299 ptd, proxy->getBridge()->getCpp2Uno()); 300 argtds[i] = ptd; 301 } else { 302 args[i] = reinterpret_cast< void * >(callStack[stackPos]); 303 argtds[i] = NULL; 304 TYPELIB_DANGER_RELEASE(ptd); 305 } 306 } 307 ++stackPos; 308 } 309 uno_Any exc; 310 uno_Any * pexc = &exc; 311 proxy->getUnoI()->pDispatcher( 312 proxy->getUnoI(), description.get(), retin, args, &pexc); 313 if (pexc != NULL) { 314 for (sal_Int32 i = 0; i < count; ++i) { 315 if (argtds[i] != NULL) { 316 if (parameters[i].bIn) { 317 uno_destructData(args[i], argtds[i], NULL); 318 } 319 TYPELIB_DANGER_RELEASE(argtds[i]); 320 } 321 } 322 if (rtd != NULL) { 323 TYPELIB_DANGER_RELEASE(rtd); 324 } 325 bridges::cpp_uno::cc5_solaris_sparc64::raiseException( 326 &exc, proxy->getBridge()->getUno2Cpp()); 327 std::abort(); // just in case 328 } 329 for (sal_Int32 i = 0; i < count; ++i) { 330 if (argtds[i] != NULL) { 331 if (parameters[i].bOut) { 332 uno_destructData( 333 cppArgs[i], argtds[i], 334 reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); 335 uno_copyAndConvertData( 336 cppArgs[i], args[i], argtds[i], 337 proxy->getBridge()->getUno2Cpp()); 338 } 339 uno_destructData(args[i], argtds[i], NULL); 340 TYPELIB_DANGER_RELEASE(argtds[i]); 341 } 342 } 343 if (directReturn) { 344 if (rtd != NULL) { 345 switch (rtd->eTypeClass) { 346 case typelib_TypeClass_VOID: 347 break; 348 case typelib_TypeClass_BOOLEAN: 349 callStack[0] = *reinterpret_cast< sal_Bool * >(retbuf); 350 break; 351 case typelib_TypeClass_BYTE: 352 callStack[0] = *reinterpret_cast< sal_Int8 * >(retbuf); 353 break; 354 case typelib_TypeClass_SHORT: 355 callStack[0] = *reinterpret_cast< sal_Int16 * >(retbuf); 356 break; 357 case typelib_TypeClass_UNSIGNED_SHORT: 358 callStack[0] = *reinterpret_cast< sal_uInt16 * >(retbuf); 359 break; 360 case typelib_TypeClass_LONG: 361 case typelib_TypeClass_ENUM: 362 callStack[0] = *reinterpret_cast< sal_Int32 * >(retbuf); 363 break; 364 case typelib_TypeClass_UNSIGNED_LONG: 365 callStack[0] = *reinterpret_cast< sal_uInt32 * >(retbuf); 366 break; 367 case typelib_TypeClass_HYPER: 368 callStack[0] = *reinterpret_cast< sal_Int64 * >(retbuf); 369 break; 370 case typelib_TypeClass_UNSIGNED_HYPER: 371 callStack[0] = *reinterpret_cast< sal_uInt64 * >(retbuf); 372 break; 373 case typelib_TypeClass_FLOAT: 374 fp_loadf0(reinterpret_cast< float * >(retbuf)); 375 break; 376 case typelib_TypeClass_DOUBLE: 377 fp_loadd0(reinterpret_cast< double * >(retbuf)); 378 break; 379 case typelib_TypeClass_CHAR: 380 callStack[0] = *reinterpret_cast< sal_Unicode * >(retbuf); 381 break; 382 case typelib_TypeClass_STRING: 383 case typelib_TypeClass_TYPE: 384 case typelib_TypeClass_SEQUENCE: 385 case typelib_TypeClass_INTERFACE: 386 callStack[0] = reinterpret_cast< unsigned long >( 387 *reinterpret_cast< void ** >(retbuf)); 388 break; 389 case typelib_TypeClass_STRUCT: 390 loadFpRegsFromStruct(rtd, retbuf); 391 // fall through 392 case typelib_TypeClass_ANY: 393 std::memcpy(callStack, retbuf, rtd->nSize); 394 break; 395 default: 396 OSL_ASSERT(false); 397 break; 398 } 399 } 400 } else if (retconv) { 401 uno_copyAndConvertData( 402 retout, retin, rtd, proxy->getBridge()->getUno2Cpp()); 403 uno_destructData(retin, rtd, NULL); 404 } 405 if (rtd != NULL) { 406 TYPELIB_DANGER_RELEASE(rtd); 407 } 408 } 409 410 extern "C" void vtableCall( 411 sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned long * callStack) 412 { 413 bool direct = static_cast< sal_uInt32 >((functionIndex) & 0x80000000) == 0; 414 functionIndex = static_cast< sal_uInt32 >(functionIndex) & 0x7FFFFFFF; 415 bridges::cpp_uno::shared::CppInterfaceProxy * proxy 416 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( 417 reinterpret_cast< char * >(callStack[direct ? 0 : 1]) - 418 vtableOffset); 419 typelib_InterfaceTypeDescription * type = proxy->getTypeDescr(); 420 OSL_ASSERT(functionIndex < type->nMapFunctionIndexToMemberIndex); 421 sal_Int32 pos = type->pMapFunctionIndexToMemberIndex[functionIndex]; 422 css::uno::TypeDescription desc(type->ppAllMembers[pos]); 423 switch (desc.get()->eTypeClass) { 424 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 425 if (type->pMapMemberIndexToFunctionIndex[pos] == functionIndex) { 426 // Getter: 427 call( 428 proxy, desc, direct, 429 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( 430 desc.get())->pAttributeTypeRef, 431 0, NULL, callStack); 432 } else { 433 // Setter: 434 typelib_MethodParameter param = { 435 NULL, 436 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( 437 desc.get())->pAttributeTypeRef, 438 true, false }; 439 call(proxy, desc, true, NULL, 1, ¶m, callStack); 440 } 441 break; 442 case typelib_TypeClass_INTERFACE_METHOD: 443 switch (functionIndex) { 444 case 1: 445 proxy->acquireProxy(); 446 break; 447 case 2: 448 proxy->releaseProxy(); 449 break; 450 case 0: 451 { 452 typelib_TypeDescription * td = NULL; 453 TYPELIB_DANGER_GET( 454 &td, 455 reinterpret_cast< css::uno::Type * >( 456 callStack[2])->getTypeLibType()); 457 if (td != NULL) { 458 css::uno::XInterface * ifc = NULL; 459 proxy->getBridge()->getCppEnv()->getRegisteredInterface( 460 proxy->getBridge()->getCppEnv(), 461 reinterpret_cast< void ** >(&ifc), 462 proxy->getOid().pData, 463 reinterpret_cast< typelib_InterfaceTypeDescription * >( 464 td)); 465 if (ifc != NULL) { 466 uno_any_construct( 467 reinterpret_cast< uno_Any * >(callStack[0]), &ifc, 468 td, 469 reinterpret_cast< uno_AcquireFunc >( 470 css::uno::cpp_acquire)); 471 ifc->release(); 472 TYPELIB_DANGER_RELEASE(td); 473 break; 474 } 475 TYPELIB_DANGER_RELEASE(td); 476 } 477 } // fall through 478 default: 479 call( 480 proxy, desc, direct, 481 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( 482 desc.get())->pReturnTypeRef, 483 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( 484 desc.get())->nParams, 485 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( 486 desc.get())->pParams, 487 callStack); 488 } 489 break; 490 default: 491 OSL_ASSERT(false); 492 break; 493 } 494 } 495 496 int const codeSnippetSize = 10 * 4; 497 498 unsigned char * generateCodeSnippet( 499 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, 500 bool directReturn) 501 { 502 sal_uInt32 index = functionIndex; 503 if (!directReturn) { 504 index |= 0x80000000; 505 } 506 unsigned int * p = reinterpret_cast< unsigned int * >(code); 507 OSL_ASSERT(sizeof (unsigned int) == 4); 508 // 0*4: save %sp, -176, %sp ! minimal stack frame: 509 *p++ = 0x9DE3BF50; 510 // 1*4: rd %pc, %l0: 511 *p++ = 0xA1414000; 512 // 2*4: ldx %l0, (8-1)*4, %l0: 513 *p++ = 0xE05C201C; 514 // 3*4: sethi %hi(index), %o0: 515 *p++ = 0x11000000 | (index >> 10); 516 // 4*4: or %o0, %lo(index), %o0: 517 *p++ = 0x90122000 | (index & 0x3FF); 518 // 5*4: sethi %hi(vtableOffset), %o1: 519 *p++ = 0x13000000 | (vtableOffset >> 10); 520 // 6*4: jmpl %l0, %g0, %g0: 521 *p++ = 0x81C40000; 522 // 7*4: or %o1, %lo(vtableOffset), %o1: 523 *p++ = 0x92126000 | (vtableOffset & 0x3FF); 524 // 8*4: .xword privateSnippetExecutor: 525 *reinterpret_cast< unsigned long * >(p) = 526 reinterpret_cast< unsigned long >(vtableSlotCall); 527 return code + codeSnippetSize; 528 } 529 530 } 531 532 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 533 534 bridges::cpp_uno::shared::VtableFactory::Slot * 535 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) { 536 return static_cast< Slot * >(block) + 1; 537 } 538 539 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 540 sal_Int32 slotCount) 541 { 542 return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize; 543 } 544 545 bridges::cpp_uno::shared::VtableFactory::Slot * 546 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 547 void * block, sal_Int32 slotCount) 548 { 549 Slot * slots = mapBlockToVtable(block) + 2; 550 slots[-3].fn = NULL; // RTTI 551 slots[-2].fn = NULL; // null 552 slots[-1].fn = NULL; // destructor 553 return slots + slotCount; 554 } 555 556 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 557 Slot ** slots, unsigned char * code, 558 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, 559 sal_Int32 functionCount, sal_Int32 vtableOffset) 560 { 561 (*slots) -= functionCount; 562 Slot * s = *slots; 563 for (sal_Int32 i = 0; i < type->nMembers; ++i) { 564 typelib_TypeDescription * member = 0; 565 TYPELIB_DANGER_GET(&member, type->ppMembers[i]); 566 OSL_ASSERT(member != 0); 567 switch (member->eTypeClass) { 568 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 569 // Getter: 570 (s++)->fn = code; 571 code = generateCodeSnippet( 572 code, functionOffset++, vtableOffset, 573 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( 574 reinterpret_cast< 575 typelib_InterfaceAttributeTypeDescription * >( 576 member)->pAttributeTypeRef)); 577 // Setter: 578 if (!reinterpret_cast< 579 typelib_InterfaceAttributeTypeDescription * >( 580 member)->bReadOnly) 581 { 582 (s++)->fn = code; 583 code = generateCodeSnippet( 584 code, functionOffset++, vtableOffset, true); 585 } 586 break; 587 588 case typelib_TypeClass_INTERFACE_METHOD: 589 (s++)->fn = code; 590 code = generateCodeSnippet( 591 code, functionOffset++, vtableOffset, 592 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( 593 reinterpret_cast< 594 typelib_InterfaceMethodTypeDescription * >( 595 member)->pReturnTypeRef)); 596 break; 597 598 default: 599 OSL_ASSERT(false); 600 break; 601 } 602 TYPELIB_DANGER_RELEASE(member); 603 } 604 return code; 605 } 606 607 void bridges::cpp_uno::shared::VtableFactory::flushCode( 608 unsigned char const * begin, unsigned char const * end) 609 { 610 bridges::cpp_uno::cc5_solaris_sparc64::flushCode(begin, end); 611 } 612