classes.pp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1998 by Michael Van Canneyt and Florian Klaempfl
  4. Classes unit for win32
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$H+}
  13. {$modeswitch advancedrecords}
  14. {$IF FPC_FULLVERSION>=30301}
  15. {$modeswitch FUNCTIONREFERENCES}
  16. {$define FPC_HAS_REFERENCE_PROCEDURE}
  17. {$endif}
  18. { determine the type of the resource/form file }
  19. {$define Win16Res}
  20. {$IFNDEF FPC_DOTTEDUNITS}
  21. unit Classes;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. interface
  24. {$IFDEF FPC_DOTTEDUNITS}
  25. uses
  26. System.RtlConsts,
  27. System.SysUtils,
  28. System.Types,
  29. System.SortBase,
  30. {$ifdef FPC_TESTGENERICS}
  31. System.FGL,
  32. {$endif}
  33. System.TypInfo,
  34. WinApi.Windows;
  35. {$ELSE FPC_DOTTEDUNITS}
  36. uses
  37. rtlconsts,
  38. sysutils,
  39. types,
  40. sortbase,
  41. {$ifdef FPC_TESTGENERICS}
  42. fgl,
  43. {$endif}
  44. typinfo,
  45. windows;
  46. {$ENDIF FPC_DOTTEDUNITS}
  47. type
  48. TWndMethod = procedure(var msg : TMessage) of object;
  49. function MakeObjectInstance(Method: TWndMethod): Pointer;
  50. procedure FreeObjectInstance(ObjectInstance: Pointer);
  51. function AllocateHWnd(Method: TWndMethod): HWND;
  52. procedure DeallocateHWnd(Wnd: HWND);
  53. {$i classesh.inc}
  54. implementation
  55. {$IFDEF FPC_DOTTEDUNITS}
  56. uses
  57. System.SysConst;
  58. {$ELSE FPC_DOTTEDUNITS}
  59. uses
  60. sysconst;
  61. {$ENDIF FPC_DOTTEDUNITS}
  62. { OS - independent class implementations are in /inc directory. }
  63. {$i classes.inc}
  64. type
  65. PMethodWrapperTrampoline = ^TMethodWrapperTrampoline;
  66. PWrapperBlock = ^TWrapperBlock;
  67. TMethodWrapperTrampoline = packed record
  68. Call : byte;
  69. CallOffset : PtrInt;
  70. Jmp : byte;
  71. JmpOffset : PtrInt;
  72. case Integer of
  73. 0: (Next: PMethodWrapperTrampoline; Block : PWrapperBlock);
  74. 1: (Method: TWndMethod);
  75. end;
  76. TWrapperBlock = packed record
  77. Next : PWrapperBlock;
  78. UsageCount : Longint;
  79. Trampolines : array[0..0] of TMethodWrapperTrampoline;
  80. end;
  81. var
  82. WrapperBlockList : PWrapperBlock;
  83. TrampolineFreeList : PMethodWrapperTrampoline;
  84. CritObjectInstance : TCriticalSection;
  85. function TrampolineWndProc(Window: HWND; Message, WParam: WPARAM;LParam: LPARAM): HRESULT; stdcall; assembler;
  86. asm
  87. // build up tmessage structure
  88. pushl $0
  89. movl (%eax),%ecx
  90. pushl LPARAM
  91. pushl WPARAM
  92. pushl Message
  93. // msg
  94. leal (%esp),%edx
  95. // load self
  96. movl 4(%eax),%eax
  97. // call method
  98. call %ecx
  99. addl $12,%esp
  100. // load result
  101. popl %eax
  102. end;
  103. function get_method_offset : Pointer;assembler;nostackframe;
  104. asm
  105. movl (%esp),%eax
  106. addl $5,%eax
  107. end;
  108. const
  109. SizeOfPage = 4096;
  110. function MakeObjectInstance(Method: TWndMethod): Pointer;
  111. var
  112. NewBlock : PWrapperBlock;
  113. Trampoline : PMethodWrapperTrampoline;
  114. begin
  115. EnterCriticalSection(CritObjectInstance);
  116. try
  117. if not(assigned(TrampolineFreeList)) then
  118. begin
  119. NewBlock:=VirtualAlloc(nil,SizeOfPage,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  120. NewBlock^.UsageCount:=0;
  121. NewBlock^.Next:=WrapperBlockList;
  122. WrapperBlockList:=NewBlock;
  123. Trampoline:=@NewBlock^.Trampolines;
  124. while pointer(Trampoline)+sizeof(Trampoline)<pointer(NewBlock)+SizeOfPage do
  125. begin
  126. Trampoline^.Next:=TrampolineFreeList;
  127. Trampoline^.Block:=NewBlock;
  128. TrampolineFreeList:=Trampoline;
  129. inc(Trampoline);
  130. end;
  131. end;
  132. Trampoline:=TrampolineFreeList;
  133. TrampolineFreeList:=TrampolineFreeList^.Next;
  134. // inc(Trampoline^.Block^.UsageCount);
  135. Trampoline^.Call:=$e8;
  136. Trampoline^.CallOffset:=pointer(@get_method_offset)-pointer(@Trampoline^.Call)-5;
  137. Trampoline^.Jmp:=$e9;
  138. Trampoline^.JmpOffset:=pointer(@TrampolineWndProc)-pointer(@Trampoline^.Jmp)-5;
  139. Trampoline^.Method:=Method;
  140. Result:=Trampoline;
  141. finally
  142. LeaveCriticalSection(CritObjectInstance);
  143. end;
  144. end;
  145. procedure FreeObjectInstance(ObjectInstance: Pointer);
  146. begin
  147. EnterCriticalSection(CritObjectInstance);
  148. try
  149. // block gets overwritten by method dec(PMethodWrapperTrampoline(ObjectInstance)^.Block^.UsageCount);
  150. PMethodWrapperTrampoline(ObjectInstance)^.Next:=TrampolineFreeList;
  151. TrampolineFreeList:=PMethodWrapperTrampoline(ObjectInstance);
  152. finally
  153. LeaveCriticalSection(CritObjectInstance);
  154. end;
  155. end;
  156. procedure DeleteInstBlockList;
  157. var
  158. hp : PWrapperBlock;
  159. begin
  160. EnterCriticalSection(CritObjectInstance);
  161. try
  162. while assigned(WrapperBlockList) do
  163. begin
  164. hp:=WrapperBlockList^.Next;
  165. if VirtualFree(WrapperBlockList,4096,MEM_DECOMMIT) then
  166. VirtualFree(WrapperBlockList,0,MEM_RELEASE);
  167. WrapperBlockList:=hp;
  168. end;
  169. finally
  170. LeaveCriticalSection(CritObjectInstance);
  171. end;
  172. end;
  173. function AllocateHWnd(Method: TWndMethod): HWND;
  174. begin
  175. { dummy }
  176. runerror(217);
  177. Result:=0;
  178. end;
  179. procedure DeallocateHWnd(Wnd: HWND);
  180. begin
  181. { dummy }
  182. runerror(217);
  183. end;
  184. initialization
  185. WrapperBlockList:=nil;
  186. TrampolineFreeList:=nil;
  187. InitCriticalSection(CritObjectInstance);
  188. CommonInit;
  189. finalization
  190. CommonCleanup;
  191. DeleteInstBlockList;
  192. DoneCriticalSection(CritObjectInstance);
  193. end.