nielsAD / lape

Scripting engine with Pascal-like syntax for FPC and Delphi
112 stars 26 forks source link

New evalprocs for pointer indexing and range checking #200

Closed ollydev closed 2 months ago

ollydev commented 2 months ago

New unit lpeval_extra which contain extra evalulation methods that do more than basic ops.

- Pointer indexing is now done in a evalproc for common sizes (4, 8, 16, 24, 32). Previously two eval functions were needed (op_add, op_multiply) now combined to one like so:

  procedure lpePointerIndexBy4_WithUInt8(const Dest, Left, Right: Pointer); {$IFDEF Lape_CDECL}cdecl;{$ENDIF}
  begin
    PPointer(Dest)^ := PByte(PPointer(Left)^) + (PUInt8(Right)^ * 4);
  end;

- Dynarray rangechecking is now also done in a single evalproc Previously two variables were assigned to the stack (two evalprocs) then a nested method in lpinterpeter was called, now is:

  procedure lpeDynArrayRangeCheck_WithInt32(const Dest, Left, Right: Pointer); {$IFDEF Lape_CDECL}cdecl;{$ENDIF}
  begin
    if (PPointer(Left)^ = nil) or ((PInt32(Right)^ < 0) or (PInt32(Right)^ >{$IFDEF DELPHI}={$ENDIF} PSizeInt(PPointer(Left)^)[-1])) then
      if (PPointer(Left)^ <> nil) then
        LapeExceptionFmt(lpeIndexOutOfRange, [PInt32(Right)^, 0, PSizeInt(PPointer(Left)^)[-1] {$IFDEF DELPHI}-1{$ENDIF}])
      else
        LapeExceptionFmt(lpeIndexOutOfRange, [PInt32(Right)^, 0, -1]);
  end;

With running SciMark as a benchmark:

Before:

  With range checking ~ 39 sec
  Without range checking ~ 29 sec

After:

  With range checking ~31.5 sec
  Without range checking ~24.5 sec

~ 20% faster running Scimark :partying_face: