classes.pp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. {$IF DEFINED(CPUARM) or DEFINED(CPUAARCH64) }
  46. intrinsics,
  47. {$ENDIF}
  48. windows;
  49. {$ENDIF FPC_DOTTEDUNITS}
  50. type
  51. TWndMethod = procedure(var msg : TMessage) of object;
  52. function MakeObjectInstance(Method: TWndMethod): Pointer;
  53. procedure FreeObjectInstance(ObjectInstance: Pointer);
  54. function AllocateHWnd(Method: TWndMethod): HWND;
  55. procedure DeallocateHWnd(Wnd: HWND);
  56. {$i classesh.inc}
  57. implementation
  58. {$IFDEF FPC_DOTTEDUNITS}
  59. uses
  60. System.SysConst;
  61. {$ELSE FPC_DOTTEDUNITS}
  62. uses
  63. sysconst;
  64. {$ENDIF FPC_DOTTEDUNITS}
  65. { OS - independent class implementations are in /inc directory. }
  66. {$i classes.inc}
  67. type
  68. PMethodWrapperTrampoline = ^TMethodWrapperTrampoline;
  69. PWrapperBlock = ^TWrapperBlock;
  70. TMethodWrapperTrampoline = packed record
  71. Call : byte;
  72. CallOffset : PtrInt;
  73. Jmp : byte;
  74. JmpOffset : PtrInt;
  75. case Integer of
  76. 0: (Next: PMethodWrapperTrampoline; Block : PWrapperBlock);
  77. 1: (Method: TWndMethod);
  78. end;
  79. TWrapperBlock = packed record
  80. Next : PWrapperBlock;
  81. UsageCount : Longint;
  82. Trampolines : array[0..0] of TMethodWrapperTrampoline;
  83. end;
  84. var
  85. WrapperBlockList : PWrapperBlock;
  86. TrampolineFreeList : PMethodWrapperTrampoline;
  87. CritObjectInstance : TCriticalSection;
  88. function TrampolineWndProc(Window: HWND; Message, WParam: WPARAM;LParam: LPARAM): HRESULT; stdcall; assembler;
  89. asm
  90. // build up tmessage structure
  91. pushl $0
  92. movl (%eax),%ecx
  93. pushl LPARAM
  94. pushl WPARAM
  95. pushl Message
  96. // msg
  97. leal (%esp),%edx
  98. // load self
  99. movl 4(%eax),%eax
  100. // call method
  101. call %ecx
  102. addl $12,%esp
  103. // load result
  104. popl %eax
  105. end;
  106. function get_method_offset : Pointer;assembler;nostackframe;
  107. asm
  108. movl (%esp),%eax
  109. addl $5,%eax
  110. end;
  111. const
  112. SizeOfPage = 4096;
  113. function MakeObjectInstance(Method: TWndMethod): Pointer;
  114. var
  115. NewBlock : PWrapperBlock;
  116. Trampoline : PMethodWrapperTrampoline;
  117. begin
  118. EnterCriticalSection(CritObjectInstance);
  119. try
  120. if not(assigned(TrampolineFreeList)) then
  121. begin
  122. NewBlock:=VirtualAlloc(nil,SizeOfPage,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  123. NewBlock^.UsageCount:=0;
  124. NewBlock^.Next:=WrapperBlockList;
  125. WrapperBlockList:=NewBlock;
  126. Trampoline:=@NewBlock^.Trampolines;
  127. while pointer(Trampoline)+sizeof(Trampoline)<pointer(NewBlock)+SizeOfPage do
  128. begin
  129. Trampoline^.Next:=TrampolineFreeList;
  130. Trampoline^.Block:=NewBlock;
  131. TrampolineFreeList:=Trampoline;
  132. inc(Trampoline);
  133. end;
  134. end;
  135. Trampoline:=TrampolineFreeList;
  136. TrampolineFreeList:=TrampolineFreeList^.Next;
  137. // inc(Trampoline^.Block^.UsageCount);
  138. Trampoline^.Call:=$e8;
  139. Trampoline^.CallOffset:=pointer(@get_method_offset)-pointer(@Trampoline^.Call)-5;
  140. Trampoline^.Jmp:=$e9;
  141. Trampoline^.JmpOffset:=pointer(@TrampolineWndProc)-pointer(@Trampoline^.Jmp)-5;
  142. Trampoline^.Method:=Method;
  143. Result:=Trampoline;
  144. finally
  145. LeaveCriticalSection(CritObjectInstance);
  146. end;
  147. end;
  148. procedure FreeObjectInstance(ObjectInstance: Pointer);
  149. begin
  150. EnterCriticalSection(CritObjectInstance);
  151. try
  152. // block gets overwritten by method dec(PMethodWrapperTrampoline(ObjectInstance)^.Block^.UsageCount);
  153. PMethodWrapperTrampoline(ObjectInstance)^.Next:=TrampolineFreeList;
  154. TrampolineFreeList:=PMethodWrapperTrampoline(ObjectInstance);
  155. finally
  156. LeaveCriticalSection(CritObjectInstance);
  157. end;
  158. end;
  159. procedure DeleteInstBlockList;
  160. var
  161. hp : PWrapperBlock;
  162. begin
  163. EnterCriticalSection(CritObjectInstance);
  164. try
  165. while assigned(WrapperBlockList) do
  166. begin
  167. hp:=WrapperBlockList^.Next;
  168. if VirtualFree(WrapperBlockList,4096,MEM_DECOMMIT) then
  169. VirtualFree(WrapperBlockList,0,MEM_RELEASE);
  170. WrapperBlockList:=hp;
  171. end;
  172. finally
  173. LeaveCriticalSection(CritObjectInstance);
  174. end;
  175. end;
  176. function AllocateHWnd(Method: TWndMethod): HWND;
  177. begin
  178. { dummy }
  179. runerror(217);
  180. Result:=0;
  181. end;
  182. procedure DeallocateHWnd(Wnd: HWND);
  183. begin
  184. { dummy }
  185. runerror(217);
  186. end;
  187. initialization
  188. WrapperBlockList:=nil;
  189. TrampolineFreeList:=nil;
  190. InitCriticalSection(CritObjectInstance);
  191. CommonInit;
  192. finalization
  193. CommonCleanup;
  194. DeleteInstBlockList;
  195. DoneCriticalSection(CritObjectInstance);
  196. end.