Skip to content

Commit e1e7859

Browse files
author
pyscripter
committed
Patch by Andrey Gruzdev
1 parent a627fc9 commit e1e7859

File tree

1 file changed

+199
-3
lines changed

1 file changed

+199
-3
lines changed

PythonForDelphi/Components/Sources/Core/MethodCallBack.pas

+199-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ procedure FreeCallBacks;
9797
implementation
9898

9999
uses
100-
Windows, Classes;
100+
{$IFDEF MSWINDOWS}Windows,{$ENDIF} Classes;
101101

102102
type
103103
PByte = ^Byte;
@@ -136,7 +136,11 @@ procedure GetCodeMem(var ptr: PByte; size: integer);
136136
if (page = nil) or (Longint(CodeMemPages^.CodeBlocks) - Longint(Pointer(CodeMemPages)) <= (size + 3*sizeof(PCodeMemBlock))) then
137137
begin
138138
// allocate new Page
139+
{$IFDEF MSWINDOWS}
139140
page:=VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
141+
{$ELSE}
142+
page := GetMem(PageSize);
143+
{$ENDIF}
140144
page^.next:=CodeMemPages;
141145
CodeMemPages:=page;
142146
// init pointer to end of page
@@ -189,7 +193,11 @@ procedure FreeCodeMem(ptr: Pointer);
189193
CodeMemPages:=page^.Next;
190194

191195
// free the memory
196+
{$IFDEF MSWINDOWS}
192197
VirtualFree(page, 0, MEM_RELEASE);
198+
{$ELSE}
199+
FreeMem(page);
200+
{$ENDIF}
193201
end;
194202

195203
exit;
@@ -233,7 +241,10 @@ function GetOfObjectCallBack( CallBack: TCallBack;
233241
argnum, calltype);
234242
end;
235243

236-
function GetCallBack( self: TObject; method: Pointer;
244+
{$IFDEF MSWINDOWS}
245+
{$IFNDEF CPUX64}
246+
// win32 inplementation
247+
function GetCallBack( self: TObject; method: Pointer;
237248
argnum: Integer; calltype: tcalltype): Pointer;
238249
const
239250
// Short handling of stdcalls:
@@ -307,6 +318,187 @@ function GetCallBack( self: TObject; method: Pointer;
307318
end;
308319
result := Q;
309320
end;
321+
{$ELSE}
322+
procedure test;
323+
asm
324+
mov r9,[rbp+$2020]
325+
end;
326+
327+
// win 64 implementation
328+
function GetCallBack( self: TObject; method: Pointer;
329+
argnum: Integer; calltype: tcalltype): Pointer;
330+
const
331+
// 64 bit
332+
c64stack: array[0..14] of byte = (
333+
$48, $81, $ec, 00, 00, 00, 00,// sub rsp,$0
334+
$4c, $89, $8c, $24, $20, 00, 00, 00// mov [rsp+$20],r9
335+
);
336+
337+
c64copy: array[0..14] of byte = (
338+
$4c, $8b, $8d, 00, 00, 00, 00,// mov r9,[rbp+0]
339+
$4c, $89, $8c, $24, 00, 00, 00, 00// mov [rsp+0],r9
340+
);
341+
342+
c64regs: array[0..28] of byte = (
343+
$4d, $89, $c1, // mov r9,r8
344+
$49, $89, $d0, // mov r8,rdx
345+
$48, $89, $ca, // mov rdx,rcx
346+
$48, $b9, 00, 00, 00, 00, 00, 00, 00, 00, // mov rcx, self
347+
$48, $b8, 00, 00, 00, 00, 00, 00, 00, 00 // mov rax, method
348+
);
349+
350+
c64jump: array[0..2] of byte = (
351+
$48, $ff, $e0 // jump rax
352+
);
353+
354+
c64call: array[0..10] of byte = (
355+
$48, $ff, $d0, // call rax
356+
$48, $81,$c4, 00, 00, 00, 00, // add rsp,$0
357+
$c3// ret
358+
);
359+
var
360+
i: Integer;
361+
P,Q: PByte;
362+
lCount : integer;
363+
lSize : integer;
364+
lOffset : integer;
365+
begin
366+
//test;
367+
lCount := SizeOf(c64regs);
368+
if argnum>3 then
369+
Inc(lCount,sizeof(c64stack)+(argnum-4)*sizeof(c64copy)+sizeof(c64call))
370+
else
371+
Inc(lCount,sizeof(c64jump));
372+
373+
GetCodeMem(Q,lCount);
374+
P := Q;
375+
376+
if argnum>3 then
377+
begin
378+
move(c64stack,P^,SizeOf(c64stack));
379+
Inc(P,3);
380+
lSize := (argnum +1 ) * sizeof(Int64);
381+
move(lSize,P^,sizeof(Int32));
382+
Inc(P,SizeOf(c64stack)-3);
383+
for I := 5 to argnum do
384+
begin
385+
move(c64copy,P^,SizeOf(c64copy));
386+
Inc(P,3);
387+
lOffset := (i-1)*sizeof(Int64);
388+
move(lOffset,P^,sizeof(Int32));
389+
Inc(P,8);
390+
lOffset := i*sizeof(Int64);
391+
move(lOffset,P^,sizeof(Int32));
392+
Inc(P,4);
393+
end;
394+
end;
395+
396+
move(c64regs,P^,SizeOf(c64regs));
397+
Inc(P,11);
398+
move(self,P^,SizeOf(self));
399+
Inc(P,10);
400+
move(method,P^,SizeOf(method));
401+
402+
Inc(P,SizeOf(c64regs)-21);
403+
404+
if argnum<4 then
405+
move(c64jump,P^,SizeOf(c64jump))
406+
else
407+
begin
408+
move(c64call,P^,SizeOf(c64call));
409+
Inc(P,6);
410+
lSize := (argnum+1) * sizeof(Int64);
411+
move(lSize,P^,sizeof(Int32));
412+
end;
413+
result := Q;
414+
end;
415+
{$ENDIF}
416+
{$ELSE}
417+
// 32 bit with stack align
418+
function GetCallBack( self: TObject; method: Pointer;
419+
argnum: Integer; calltype: tcalltype): Pointer;
420+
const
421+
// Short handling of stdcalls:
422+
S1: array [0..14] of byte = (
423+
$5A, //00 pop edx // pop return address
424+
$B8,0,0,0,0, //01 mov eax, self
425+
$50, //06 push eax
426+
$52, //07 push edx // now push return address
427+
// call the real callback
428+
$B8,0,0,0,0, //08 mov eax, Method
429+
$FF,$E0); //13 jmp eax
430+
431+
//Handling for ctCDECL:
432+
C1: array [0..5] of byte = (
433+
// begin of call
434+
$55, //00 push ebp
435+
$8B,$EC, //01 mov ebp, esp
436+
$83,$EC,$0); //03 sub esp, align
437+
438+
// push arguments
439+
// for i:= argnum-1 downto 0 do begin
440+
C2: array [0..3] of byte = (
441+
$8B,$45,0, //06+4*s mov eax,[ebp+8+4*i]
442+
$50); //09+4*s push eax
443+
// end;
444+
445+
// self parameter
446+
C3: array [0..17] of byte = (
447+
$B8,0,0,0,0, //06+4*s mov eax, self
448+
$50, //11+4*s push eax
449+
// call the real callback
450+
$B8,0,0,0,0, //12+4*s mov eax,Method
451+
$FF,$D0, //17+4*s call eax
452+
// clear stack
453+
$83,$C4,0, //20+4*s add esp, 4+bytes+align
454+
$5D, //23+4*s pop ebp
455+
$C3); //24+4*s ret
456+
457+
458+
459+
var
460+
bytes: Word;
461+
i: Integer;
462+
P,Q: PByte;
463+
align : integer;
464+
begin
465+
if calltype = ctSTDCALL then begin
466+
GetCodeMem(Q,15);
467+
P := Q;
468+
move(S1,P^,SizeOf(S1));
469+
Inc(P,2);
470+
move(self,P^,SizeOf(self));
471+
Inc(P,7);
472+
move(method,P^,SizeOf(method));
473+
{Inc(P,6); End of proc}
474+
end else begin {ctCDECL}
475+
bytes := argnum * 4;
476+
align := ($10 - (bytes + 4{self} + 4{address} + 4{push bp}) and $f) and $f; // align to $10 for Mac compatibility
477+
478+
GetCodeMem(Q,24+4*argnum);
479+
P := Q;
480+
move(C1,P^,SizeOf(C1));
481+
Inc(P,SizeOf(C1)-1);
482+
p^ := align;
483+
Inc(P);
484+
for i:=argnum-1 downto 0 do begin
485+
move(C2,P^,SizeOf(C2));
486+
Inc(P,2);
487+
P^:=8+4*i;
488+
Inc(P,2);
489+
end;
490+
move(C3,P^,SizeOf(C3));
491+
Inc(P,1);
492+
move(self,P^,SizeOf(self));
493+
Inc(P,6);
494+
move(method,P^,SizeOf(method));
495+
Inc(P,8);
496+
P^ := 4+bytes+align;
497+
{Inc(P,3); End of proc}
498+
end;
499+
result := Q;
500+
end;
501+
{$ENDIF}
310502

311503
procedure DeleteCallBack( Proc: Pointer);
312504
begin
@@ -324,7 +516,11 @@ procedure FreeCallBacks;
324516
nextpage := page^.Next;
325517

326518
// free the memory
327-
VirtualFree(page, 0, MEM_RELEASE);
519+
{$IFDEF MSWINDOWS}
520+
VirtualFree(page, 0, MEM_RELEASE);
521+
{$ELSE}
522+
FreeMem(page);
523+
{$ENDIF}
328524

329525
page := nextpage;
330526
end;

0 commit comments

Comments
 (0)