|
@@ -51,17 +51,98 @@ uses
|
|
|
{ OS - independent class implementations are in /inc directory. }
|
|
|
{$i classes.inc}
|
|
|
|
|
|
+type
|
|
|
+ PMethodWrapperTrampoline = ^TMethodWrapperTrampoline;
|
|
|
+ PWrapperBlock = ^TWrapperBlock;
|
|
|
+
|
|
|
+ TMethodWrapperTrampoline = packed record
|
|
|
+ Call : byte;
|
|
|
+ CallOffset : PtrInt;
|
|
|
+ Jmp : byte;
|
|
|
+ JmpOffset : PtrInt;
|
|
|
+ case Integer of
|
|
|
+ 0: (Next: PMethodWrapperTrampoline; Block : PWrapperBlock);
|
|
|
+ 1: (Method: TWndMethod);
|
|
|
+ end;
|
|
|
+
|
|
|
+ TWrapperBlock = packed record
|
|
|
+ Next : PWrapperBlock;
|
|
|
+ UsageCount : Longint;
|
|
|
+ Trampolines : array[0..0] of TMethodWrapperTrampoline;
|
|
|
+ end;
|
|
|
+
|
|
|
+var
|
|
|
+ WrapperBlockList : PWrapperBlock;
|
|
|
+ TrampolineFreeList : PMethodWrapperTrampoline;
|
|
|
+
|
|
|
+function TrampolineWndProc(Window: HWND; Message, WParam: WPARAM;LParam: LPARAM): HRESULT; stdcall; assembler;
|
|
|
+asm
|
|
|
+ // build up tmessage structure
|
|
|
+ pushl $0
|
|
|
+ movl (%eax),%ecx
|
|
|
+ pushl LPARAM
|
|
|
+ pushl WPARAM
|
|
|
+ pushl Message
|
|
|
+ // msg
|
|
|
+ leal (%esp),%edx
|
|
|
+ // load self
|
|
|
+ movl 4(%eax),%eax
|
|
|
+ // call method
|
|
|
+ call %ecx
|
|
|
+ addl $12,%esp
|
|
|
+ // load result
|
|
|
+ popl %eax
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function get_method_offset : Pointer;assembler;nostackframe;
|
|
|
+ asm
|
|
|
+ movl (%esp),%eax
|
|
|
+ addl $5,%eax
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+const
|
|
|
+ SizeOfPage = 4096;
|
|
|
+
|
|
|
+
|
|
|
function MakeObjectInstance(Method: TWndMethod): Pointer;
|
|
|
+ var
|
|
|
+ NewBlock : PWrapperBlock;
|
|
|
+ Trampoline : PMethodWrapperTrampoline;
|
|
|
begin
|
|
|
- { dummy }
|
|
|
- runerror(217);
|
|
|
+ if not(assigned(TrampolineFreeList)) then
|
|
|
+ begin
|
|
|
+ NewBlock:=VirtualAlloc(nil,SizeOfPage,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
|
|
|
+ NewBlock^.UsageCount:=0;
|
|
|
+ NewBlock^.Next:=WrapperBlockList;
|
|
|
+ WrapperBlockList:=NewBlock;
|
|
|
+ Trampoline:=@NewBlock^.Trampolines;
|
|
|
+ while pointer(Trampoline)+sizeof(Trampoline)<pointer(NewBlock)+SizeOfPage do
|
|
|
+ begin
|
|
|
+ Trampoline^.Next:=TrampolineFreeList;
|
|
|
+ Trampoline^.Block:=NewBlock;
|
|
|
+ TrampolineFreeList:=Trampoline;
|
|
|
+ inc(Trampoline);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ Trampoline:=TrampolineFreeList;
|
|
|
+ TrampolineFreeList:=TrampolineFreeList^.Next;
|
|
|
+ inc(Trampoline^.Block^.UsageCount);
|
|
|
+ Trampoline^.Call:=$e8;
|
|
|
+ Trampoline^.CallOffset:=pointer(@get_method_offset)-pointer(@Trampoline^.Call)-5;
|
|
|
+ Trampoline^.Jmp:=$e9;
|
|
|
+ Trampoline^.JmpOffset:=pointer(@TrampolineWndProc)-pointer(@Trampoline^.Jmp)-5;
|
|
|
+ Trampoline^.Method:=Method;
|
|
|
+ Result:=Trampoline;
|
|
|
end;
|
|
|
|
|
|
|
|
|
procedure FreeObjectInstance(ObjectInstance: Pointer);
|
|
|
begin
|
|
|
- { dummy }
|
|
|
- runerror(217);
|
|
|
+ dec(PMethodWrapperTrampoline(ObjectInstance)^.Block^.UsageCount);
|
|
|
+ PMethodWrapperTrampoline(ObjectInstance)^.Next:=TrampolineFreeList;
|
|
|
+ TrampolineFreeList:=PMethodWrapperTrampoline(ObjectInstance);
|
|
|
end;
|
|
|
|
|
|
|
|
@@ -79,9 +160,26 @@ procedure DeallocateHWnd(Wnd: HWND);
|
|
|
end;
|
|
|
|
|
|
|
|
|
+procedure DeleteInstBlockList;
|
|
|
+ var
|
|
|
+ hp : PWrapperBlock;
|
|
|
+ begin
|
|
|
+ while assigned(WrapperBlockList) do
|
|
|
+ begin
|
|
|
+ hp:=WrapperBlockList^.Next;
|
|
|
+ if VirtualFree(WrapperBlockList,4096,MEM_DECOMMIT) then
|
|
|
+ VirtualFree(WrapperBlockList,0,MEM_RELEASE);
|
|
|
+ WrapperBlockList:=hp;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
initialization
|
|
|
+ WrapperBlockList:=nil;
|
|
|
+ TrampolineFreeList:=nil;
|
|
|
CommonInit;
|
|
|
|
|
|
finalization
|
|
|
CommonCleanup;
|
|
|
+ DeleteInstBlockList;
|
|
|
end.
|