Skip to content

Commit e19ebb4

Browse files
committed
optimized TRefCountedObject.GetInterface
1 parent aa3fcd5 commit e19ebb4

File tree

2 files changed

+84
-43
lines changed

2 files changed

+84
-43
lines changed

Source/Base/Spring.pas

Lines changed: 84 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -397,18 +397,6 @@ TManagedInterfaceField = class(TManagedObjectField)
397397
procedure FinalizeValue(instance: Pointer); override;
398398
end;
399399

400-
const
401-
{$IF SizeOf(Pointer) = 4}
402-
PROPSLOT_MASK = $FF000000;
403-
PROPSLOT_FIELD = $FF000000;
404-
PROPSLOT_VIRTUAL = $FE000000;
405-
{$ELSEIF SizeOf(Pointer) = 8}
406-
PROPSLOT_MASK = $FF00000000000000;
407-
PROPSLOT_FIELD = $FF00000000000000;
408-
PROPSLOT_VIRTUAL = $FE00000000000000;
409-
{$ELSE OTHER_PTR_SIZE}
410-
{$MESSAGE Fatal 'Unrecognized pointer size'}
411-
{$IFEND OTHER_PTR_SIZE}
412400
strict private
413401
DefaultFields: TArray<TInitializableField>;
414402
ManagedFields: TArray<TFinalizableField>;
@@ -1303,6 +1291,7 @@ TRefCountedObject = class abstract
13031291
function QueryInterface(const IID: TGUID; out obj): HResult; stdcall;
13041292
function _AddRef: Integer; stdcall;
13051293
function _Release: Integer; stdcall;
1294+
function GetInterface(const IID: TGUID; out Obj): Boolean;
13061295
{$IFNDEF AUTOREFCOUNT}
13071296
procedure AfterConstruction; override;
13081297
procedure BeforeDestruction; override;
@@ -2027,7 +2016,7 @@ THandleFinalizer<T> = class(TInterfacedObject, IShared<T>)
20272016

20282017
{$IFDEF DELPHIXE6_UP}{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS(DefaultFieldRttiVisibility)}{$ENDIF}
20292018

2030-
TWeakReference = class abstract(TInterfacedObject)
2019+
TWeakReference = class abstract(TRefCountedObject)
20312020
private
20322021
fTarget: Pointer;
20332022
class procedure RegisterWeakRef(address: Pointer; instance: Pointer); static;
@@ -2986,6 +2975,22 @@ procedure UnregisterWeakRef(address: Pointer; const instance: TObject);
29862975
EmptyValue: TValue = ();
29872976
caReseted = caReset deprecated 'Use caReset';
29882977

2978+
ObjCastGUID: TGUID = '{CEDF24DE-80A4-447D-8C75-EB871DC121FD}';
2979+
2980+
{$IFNDEF DELPHIXE3_UP}
2981+
{$IF SizeOf(Pointer) = 4}
2982+
PROPSLOT_MASK = $FF000000;
2983+
PROPSLOT_FIELD = $FF000000;
2984+
PROPSLOT_VIRTUAL = $FE000000;
2985+
{$ELSEIF SizeOf(Pointer) = 8}
2986+
PROPSLOT_MASK = $FF00000000000000;
2987+
PROPSLOT_FIELD = $FF00000000000000;
2988+
PROPSLOT_VIRTUAL = $FE00000000000000;
2989+
{$ELSE OTHER_PTR_SIZE}
2990+
{$MESSAGE Fatal 'Unrecognized pointer size'}
2991+
{$IFEND OTHER_PTR_SIZE}
2992+
{$ENDIF}
2993+
29892994
implementation
29902995

29912996
uses
@@ -4710,39 +4715,57 @@ procedure TInitTable.TManagedObjectField.InitializeValue(instance: Pointer);
47104715

47114716
{$REGION 'TInitTable.TManagedInterfaceField'}
47124717

4713-
function InvokeImplGetter(const Self: TObject; implGetter: NativeUInt): IInterface;
4718+
procedure InvokeImplGetter(const self: TObject; implGetter: NativeUInt; var result: IInterface);
4719+
{$IFDEF PUREPASCAL}
4720+
type
4721+
{$IF defined(MSWINDOWS) or defined(OSX32)}
4722+
TGetProc = procedure (const self: TObject; var result: IInterface);
4723+
{$ELSE}
4724+
TGetProc = procedure (var result: IInterface; const self: TObject);
4725+
{$IFEND}
47144726
var
4715-
method: function: IInterface of object;
4727+
getProc: TGetProc;
47164728
begin
4717-
TMethod(method).Data := Self;
4718-
{$IF SizeOf(NativeUInt) = 4}
4719-
case implGetter of
4720-
$FF000000..$FFFFFFFF:
4721-
Result := IInterface(PPointer(PByte(Self) + (implGetter and $00FFFFFF))^);
4722-
$FE000000..$FEFFFFFF:
4723-
begin
4724-
TMethod(method).Code := PPointer(PNativeInt(Self)^ + SmallInt(implGetter))^;
4725-
Result := method;
4726-
end;
4727-
else
4728-
TMethod(method).Code := Pointer(implGetter);
4729-
Result := method;
4730-
end;
4731-
{$ELSE}
4732-
if (implGetter and $FF00000000000000) = $FF00000000000000 then
4733-
Result := IInterface(PPointer(PByte(Self) + (implGetter and $00FFFFFFFFFFFFFF))^)
4734-
else if (implGetter and $FF00000000000000) = $FE00000000000000 then
4735-
begin
4736-
TMethod(method).Code := PPointer(PNativeInt(Self)^ + SmallInt(implGetter))^;
4737-
Result := method;
4738-
end
4729+
if (implGetter and PROPSLOT_MASK) = PROPSLOT_FIELD then
4730+
Result := IInterface(PPointer(PByte(self) + (implGetter and not PROPSLOT_MASK))^)
47394731
else
47404732
begin
4741-
TMethod(method).Code := Pointer(implGetter);
4742-
Result := method;
4733+
if (implGetter and PROPSLOT_MASK) = PROPSLOT_VIRTUAL then
4734+
getProc := PPointer(PNativeInt(self)^ + SmallInt(implGetter))^
4735+
else
4736+
getProc := Pointer(implGetter);
4737+
{$IF defined(MSWINDOWS) or defined(OSX32)}
4738+
GetProc(self, result);
4739+
{$ELSE}
4740+
GetProc(result, self);
4741+
{$IFEND}
47434742
end;
4744-
{$IFEND}
47454743
end;
4744+
{$ELSE}
4745+
{$IFDEF CPUX86}
4746+
asm
4747+
xchg edx,ecx
4748+
cmp ecx,PROPSLOT_FIELD
4749+
jae @@isField
4750+
cmp ecx,PROPSLOT_VIRTUAL
4751+
jb @@isStaticMethod
4752+
4753+
movsx ecx,cx
4754+
add ecx,[eax]
4755+
jmp dword ptr [ecx]
4756+
4757+
@@isStaticMethod:
4758+
jmp ecx
4759+
4760+
@@isField:
4761+
and ecx,not PROPSLOT_MASK
4762+
add ecx,eax
4763+
mov eax,edx
4764+
mov edx,[ecx]
4765+
jmp System.@IntfCopy
4766+
end;
4767+
{$ENDIF}
4768+
{$ENDIF}
47464769

47474770
constructor TInitTable.TManagedInterfaceField.Create(offset: Integer;
47484771
fieldType: PTypeInfo; cls: TClass; const factory: TFunc<PTypeInfo,Pointer>;
@@ -4766,7 +4789,7 @@ function TInitTable.TManagedInterfaceField.CreateInstance: Pointer;
47664789
else
47674790
begin
47684791
Result := nil;
4769-
IInterface(Result) := InvokeImplGetter(obj, fEntry.ImplGetter);
4792+
InvokeImplGetter(obj, fEntry.ImplGetter, IInterface(Result));
47704793
end;
47714794
end;
47724795

@@ -7139,6 +7162,26 @@ function TRefCountedObject.AsObject: TObject;
71397162
Result := Self;
71407163
end;
71417164

7165+
function TRefCountedObject.GetInterface(const IID: TGUID; out Obj): Boolean;
7166+
var
7167+
interfaceEntry: PInterfaceEntry;
7168+
begin
7169+
Pointer(Obj) := nil;
7170+
interfaceEntry := GetInterfaceEntry(IID);
7171+
if interfaceEntry <> nil then
7172+
begin
7173+
if interfaceEntry.IOffset <> 0 then
7174+
begin
7175+
Pointer(Obj) := Pointer(PByte(Self) + interfaceEntry.IOffset);
7176+
if Pointer(Obj) <> nil then IInterface(Obj)._AddRef;
7177+
end
7178+
else
7179+
InvokeImplGetter(Self, interfaceEntry.ImplGetter, IInterface(Obj));
7180+
end else if IID = ObjCastGUID then
7181+
Pointer(Obj) := Pointer(Self);
7182+
Result := Pointer(Obj) <> nil;
7183+
end;
7184+
71427185
{$IFNDEF AUTOREFCOUNT}
71437186
function TRefCountedObject.GetRefCount: Integer;
71447187
begin

Source/Core/Interception/Spring.Interception.InterfaceProxy.pas

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,6 @@ procedure TInterfaceProxy.HandleInvoke(Method: TRttiMethod;
188188
end;
189189

190190
function TInterfaceProxy.QueryInterface(const IID: TGUID; out Obj): HResult;
191-
const
192-
ObjCastGUID: TGUID = '{CEDF24DE-80A4-447D-8C75-EB871DC121FD}';
193191
var
194192
i: Integer;
195193
begin

0 commit comments

Comments
 (0)