| 450 | } |
| 451 | |
| 452 | NO_SANITIZE_ADDRESS |
| 453 | void ScriptingType::SetupScriptObjectVTable(void* object, ScriptingTypeHandle baseTypeHandle, int32 wrapperIndex) |
| 454 | { |
| 455 | // Analyze vtable size |
| 456 | void** vtable = *(void***)object; |
| 457 | const int32 prefixSize = GetVTablePrefix(); |
| 458 | int32 entriesCount = 0; |
| 459 | while (vtable[entriesCount] && entriesCount < 200) |
| 460 | entriesCount++; |
| 461 | |
| 462 | // Calculate total vtable size by adding all implemented interfaces that use virtual methods |
| 463 | const int32 size = entriesCount * sizeof(void*); |
| 464 | int32 totalSize = prefixSize + size; |
| 465 | int32 interfacesCount = 0; |
| 466 | for (ScriptingTypeHandle e = baseTypeHandle; e;) |
| 467 | { |
| 468 | const ScriptingType& eType = e.GetType(); |
| 469 | auto interfaces = eType.Interfaces; |
| 470 | if (interfaces) |
| 471 | { |
| 472 | while (interfaces->InterfaceType) |
| 473 | { |
| 474 | auto& interfaceType = interfaces->InterfaceType->GetType(); |
| 475 | if (interfaceType.Interface.SetupScriptObjectVTable) |
| 476 | { |
| 477 | void** vtableInterface = *(void***)((byte*)object + interfaces->VTableOffset); |
| 478 | int32 interfaceCount = 0; |
| 479 | while (vtableInterface[interfaceCount] && interfaceCount < 200) |
| 480 | interfaceCount++; |
| 481 | totalSize += prefixSize + interfaceCount * sizeof(void*); |
| 482 | interfacesCount++; |
| 483 | } |
| 484 | interfaces++; |
| 485 | } |
| 486 | } |
| 487 | e = eType.GetBaseType(); |
| 488 | } |
| 489 | |
| 490 | // Duplicate vtable |
| 491 | void** scriptVTable = (void**)((byte*)Platform::Allocate(totalSize, 16) + prefixSize); |
| 492 | Utilities::UnsafeMemoryCopy((byte*)scriptVTable - prefixSize, (byte*)vtable - prefixSize, prefixSize + size); |
| 493 | |
| 494 | // Override vtable entries |
| 495 | if (interfacesCount) |
| 496 | Script.InterfacesOffsets = (uint16*)Platform::Allocate(interfacesCount * sizeof(uint16*), 16); |
| 497 | int32 interfaceOffset = size; |
| 498 | interfacesCount = 0; |
| 499 | for (ScriptingTypeHandle e = baseTypeHandle; e;) |
| 500 | { |
| 501 | const ScriptingType& eType = e.GetType(); |
| 502 | |
| 503 | if (eType.Script.SetupScriptObjectVTable) |
| 504 | { |
| 505 | // Override vtable entries for this class |
| 506 | eType.Script.SetupScriptObjectVTable(Script.ScriptVTable, Script.ScriptVTableBase, scriptVTable, entriesCount, wrapperIndex); |
| 507 | } |
| 508 | |
| 509 | auto interfaces = eType.Interfaces; |
nothing calls this directly
no test coverage detected