Friday, April 27, 2007

Psst, a special price for you, my friend...

An item that may interest you is available at eBay now, click here.

PS: I still have another Delphi 2007 licence.

Tuesday, April 17, 2007

DN4DP#7: Inlined routines

This post continues the series of The Delphi Language Chapter teasers from Jon Shemitz’ .NET 2.0 for Delphi Programmers book. Last time we covered the new for in loop and the pattern for introducing enumeration support to your own classes. This post includes the section on the inlining support of the compiler.

Note that I do not get any royalties from the book and I highly recommend that you get your own copy – for instance at Amazon.

"Inlined routines

From Chapter 4 we know that the .NET Just-In-Time (JIT) compiler will automatically perform optimizations, including inlining small and simple methods at call sites. In addition to this JIT inlining, Delphi now supports explicit inlining of non-virtual routines, both in .NET and Win32.

function InlineMeToo(const Value: integer): integer; inline;
begin
Result := Value * 200 div 300;
end;

The inline directive is just a hint to the Delphi compiler that it should try to expand the code inline whenever the routine is called, at compile time. The exact rules of what and when it can be inlined differ slightly between the two platforms.

In .NET, Delphi inlining occurs at the IL level. This means that the IL code generated at the call site must obey CLR limitations and rules regarding member visibility. This limitation is mitigated by the less constrained JIT inlining that occurs at runtime.

The Win32 inlining support was made more aggressive in Delphi 2006 - now even methods that access private members can be inlined. Assembly (BASM) code cannot be inlined.

The rest of the inlining restrictions are common for both platforms and the most important ones are


  • no inlining across package boundaries
  • the inlined routine cannot access implementation section identifiers
  • the call site must have access to all identifiers used in the inlined routine


Note The last point means that unless the call site unit uses the units required by the routine, the routine cannot be inlined. When this happens, the compiler emits a hint like this

[Pascal Hint] InlinedRoutinesU.pas(14): H2443 Inline function 'InlineMe' has not been expanded because unit 'RequiredUnit' is not specified in USES list

To resolve the issue, add the missing unit name to the call site's uses clause.


The {$INLINE ON/AUTO/OFF} compiler directive can be used both at the definition and the call site. The OFF mode turns off all inlining. The default ON setting tries to inline routines explicitly marked inline. AUTO additionally tries to inline all small routines (consisting of less than 32 bytes of machine or IL code).




Caution Be careful with inlining too much code, the potential code size increase may actually reduce performance.




"


Update [May 12th 2007]:


In addition to the inline restrictions mentioned above I should have included the issue of implementation order.


If the inlined method is called from the same unit, the implementation of the inline method must have been "seen" by the compiler. In other words, the inlined implementation should preceed the call.

For example:

type
Foo = class
procedure A; inline;
procedure B;
end;

procedure TFoo.B;
begin
A; // note: Call to A is *not* inlined here
end;

procedure TFoo.A;
begin
// code
end;

Change this to:

type
Foo = class
procedure A; inline;
procedure B;
end;

procedure TFoo.A;
begin
// code
end;

procedure TFoo.B;
begin
A; // note: Call to A *is* inlined here
end;

Wednesday, April 11, 2007

Subversion in Delphi's Tools menu

Joe White writes about how to add Tools menu items with Subversion commands
here.

For some reason, the Submit button didn't work on his Comments page (running IE6), so I'll just write my comment here:

Nice, thanks!

I've been meaning to do the same thing for a while, but kept postponing it. Shame about the space-before-macro requirement in the Tools menu - you should probably log it in QC.

I didn't have Ruby installed so I wrote a simple online .Bat file instead:

"c:/program files/tortoisesvn/bin/tortoiseproc.exe" /command:%1 /path:%2 /notempfile

Then I create the Tools items with:
Program: c:\windows\system32\cmd.exe
Parameters: /C C:\SvnPas\Utils\Batch\SvnCmd.Bat diff $EDNAME $SAVEALL

Works fine!

Sunday, April 08, 2007

Hack#16: Published field RTTI replacement trick

We're back to fixing the interesting (learning-wise) problem of the flickering TProgressBar on Windows Vista. We have already looked at two relatively dirty and intrusive hacks that either overwrites the TClass reference inside each progress bar instance or overwrites the dynamic method table pointer of the original TProgressBar VMT. There are other related code page overwrite hacks that we may look at in the future (overwriting a virtual method slot, for instance), but this time we will look at a much simpler and (IMO) more elegant solution; tricking the compiler to replace the RTTI it generates for the component field on the for with a fixed version of TProgressBar.

As you know (if you have read the published fields and details articles), the IDE inserts component fields into the unnamed published section of your form class declaration as you drop components and controls on to the form at design time. Since the fields are published, the compiler generates RTTI for them - including the name, type and offset of the field.

For instance, creating a new form and dropping a couple of labels, a button and a progress bar on it, the IDE has generated the following code.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls;

type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
ProgressBar1: TProgressBar;
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

end.

The published field RTTI includes the type of each field - encoded as a TClass reference. But how does the compiler know what TClass to use? By using the normal Pascal scoping rules, of course. TLabel and TButton both refers to the classes defined in the StdCtrls unit. For TProgressBar the compiler first checks the StdCtrls unit, but failing to find any TProgressBar class there, it looks in ComCtrls unit and finds it there.


Here lies the clue to our trick - we can simply add another unit to the interface uses clause, one that contains a fixed version of TProgressBar. We just have to make sure this unit is listed after the unit that contains the original TProgressBar (ComCtrls in this case). Let's get to it.


First we write (yet another version of) the fixed TProgressClass and put it inside an aptly named unit.

unit HVProgressBarVistaFix;

interface

uses Messages, ComCtrls;

type
TProgressBar = class(ComCtrls.TProgressBar)
private
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd);
message WM_ERASEBKGND;
end;

implementation

procedure TProgressBar.WMEraseBkgnd(var Message: TWmEraseBkgnd);
begin
DefaultHandler(Message);
end;

end.

Notice two things; the class must have the same name as the original class 'TProgressBar' and to avoid a compiler error message like



[Error] HVProgressBarVistaFix.pas(8): Type 'TProgressBar' is not yet completely defined


The class we inherit from has to be explicitly qualified with the unit it comes from 'ComCtrls.TProgressBar'.


With this simple unit in hand, we can fix the progress bar flickering simply by referencing the HVProgressBarVistaFix unit from all forms that uses progress bars (search your code for TProgressBar). Make sure it is listed last in the uses clause of the interface section.

uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, HVProgressBarVistaFix;

This ensures that the compiler inserts the TClass reference of our fixed version of the TProgressBar class into the published field RTTI tables of the form. When the streaming system reads the .dfm at runtime it uses these published field tables (read the details here) to find the TClass reference (or TComponentClass reference, to be exact) and uses it (and the virtual constructor of TComponent) to create the component. Because we have replaced the ComCtrls.TProgressBar class reference with our fixed version in HVProgressBarVistaFix.TProgressBar, it is our class that will be created.


With this simple kind of hack you can introduce any number of fixes, overriding virtual, dynamic or message methods, for instance. Look ma - no dirty hands! ;).

Tuesday, April 03, 2007

DN4DP#6: Enumerating collections

This post continues the series of The Delphi Language Chapter teasers from Jon Shemitz’ .NET 2.0 for Delphi Programmers book. Last time we showed how it is now possible to override the meaning of language operators. This time we'll cover the new for in loop and the pattern for introducing enumeration support to your own classes.

Note that I do not get any royalties from the book and I highly recommend that you get your own copy – for instance at Amazon.

"Enumerating collections

To make it easier and more convenient to enumerate over the contents of collections the traditional for statement has been extended into a for in statement. In general the for in syntax is

var
Element: ElementType;
begin
for Element in Collection do
Writeln(Element.Member);
end;

ElementType must be assignment compatible with the type of the actual elements stored inside the collection. The collection must implement the enumerator pattern or be of an array, string or set type. You only have read access to the Element itself, but you can change any properties and fields it references.

All .NET collections and most VCL container classes like TList and TStrings implements the required pattern, so now you can transform old code like

var
S: string;
i: integer;
begin
for i := 0 to MyStrings.Count-1 do
begin
S := MyStrings[i];
writeln(S);
end;
end;

into the simpler, less error prone, but equivalent

var
S: string;
begin
for S in MyStrings do
writeln(S);
end;

To enable for in for your own collection classes, you need to implement the enumerator pattern. This involves writing a GetEnumerator function that returns an instance (class, record or interface) that implements a Boolean MoveNext function and a Current property. In .NET you can also achieve this by implementing the IEnumerable interface. In Win32 these methods must be public.

type
TMyObjectsEnumerator = class
public
function GetCurrent: integer;
function MoveNext: Boolean;
property Current: integer read GetCurrent;
end;
TMyObjects = class
public
function GetEnumerator: TMyObjectsEnumerator;
end;

The EnumeratingCollections project demonstrates the differences between the old manual enumeration loops and the new for in loops. It also includes an example of how to write your own classes that support for in enumeration."

Saturday, March 31, 2007

DN4DP#5: Redefining the operators

This post continues the series of The Delphi Language Chapter teasers from Jon Shemitz’ .NET 2.0 for Delphi Programmers book. Last time we talked about the new record syntax. This time we will look at the exciting new operator overloading capabilities.

Note that I do not get any royalties from the book and I highly recommend that you get your own copy – for instance at Amazon.

"Redefining the operators

Long-time Delphi programmers have looked at the operator overloading features of other languages (such as C++) with both fear and envy. The ability for user code to redefine the meaning of operators applied to an instance of a specific class is powerful and elegant if used properly, but it can be highly confusing and erroneous if used improperly.

Delphi now supports operator overloading. This is an advanced concept where a class or (more commonly, and the only kind supported in Win32) a record can have a special method called when a specific operator (such as +, -, /, *, div, mod, etc) is applied to an instance of the class or record. To define operator overloads you must define class operator functions with specific names for each operator. See the Delphi language documentation for the full list of class operator names.

In addition to normal operators, implicit and explicit casts (or conversions) can be implemented. The OperatorOverloading project demonstrates the potentially confusing aspects of operator overloading. It defines a TStrangeInt record where the operator semantics have been reversed:

type
TStrangeInt = record
public
Value: Integer;
class operator Add(const Left, Right: TStrangeInt):
TStrangeInt; inline;
class operator Subtract(const Left, Right: TStrangeInt):
TStrangeInt; inline;
class operator Multiply(const Left, Right: TStrangeInt):
TStrangeInt; inline;
class operator Divide(const Left, Right: TStrangeInt):
TStrangeInt; inline;
class operator Implicit(const AValue: Integer):
TStrangeInt; inline;
class operator Implicit(const AValue: TStrangeInt):
Integer; inline;
class operator Implicit(const AValue: TStrangeInt):
string; inline;
class operator Explicit(const AValue: Double):
TStrangeInt; inline;
end;

The implementation of a class operator method should create and return a new record or class instance and not modify any of the parameters. Often operator methods are very short and simple and thus perfect inline candidates[1] (inline routines are covered later in this Chapter).

class operator TStrangeInt.Add(const Left, Right: 
TStrangeInt): TStrangeInt;
begin
Result.Value := Left.Value - Right.Value;
end;

Invoking the overloaded operators is just a matter of declaring an instance of the record type and using the standard Delphi operators on it.

var
Strange: TStrangeInt;
StrangeResult: TStrangeInt;
begin
Strange := 42;
StrangeResult := Strange + Strange * 3;
end;

Because of the reversed TStrangeInt implementation, StrangeResult will be 28 instead of the expected 168. See Chapter 7 for more details on operator overloading.

Tip For a more complete example of operator overloading, see the Borland.Vcl.Complex .NET unit (or the Vassbotn.Vcl.Complex unit in the Demos\DelphiWin32\VCLWin32\ComplexNumbers\ folder for the corresponding Win32 unit).




[1] Marking overloaded operators with inline is purely optional, of course. Currently (Delphi 2006) it seems like the compiler manages to inline all simple operators except the Implicit and Explicit conversion operators."

Friday, March 23, 2007

Hack#15: Overriding message and dynamic methods at run-time

Last time we looked at a way of completely changing the class of a running object instance. As we discussed there, that hacking technique had a number of problems. But there are many ways to skin a cat (sorry, cat lovers!), and in the case of trying to fix the TProgressBar flickering issue on Windows Vista without changing the interface declaration of TProgressBar there are at least three other possible solutions.

One of these solution is to patch the existing TProgressBar VMT at runtime. We know from earlier articles that the VMT contains a load of information about a class - including an array of all virtual method implementation (the actual VMT - virtual method table) and a sparse array of all overridden and introduced dynamic and message methods (known as the DMT or dynamic method table). In this article we will look at how we can patch an existing class VMT and replace the DMT with one that fits our need.

Note that the compiler stores the class VMT tables in write-protected code pages (even though they do not strictly contain executable code). This means that if we naively try to overwrite parts of the VMT we will get access violations triggered by the hardware memory protection system. The clean way of writing self-modifying code is to use the VirtualProtect API to change the protection of the memory pages to allow writing before performing the patch, then restoring the original protection when we're done. Here is a routine that will safely overwrite a 4-byte DWORD in the code segment:

procedure PatchCodeDWORD(Code: PDWORD; Value: DWORD);
// Self-modifying code - change one DWORD in the code segment
var
RestoreProtection, Ignore: DWORD;
begin
if VirtualProtect(Code, SizeOf(Code^), PAGE_EXECUTE_READWRITE,
RestoreProtection) then
begin
Code^ := Value;
VirtualProtect(Code, SizeOf(Code^), RestoreProtection, Ignore);
FlushInstructionCache(GetCurrentProcess, Code, SizeOf(Code^));
end;
end;

To be on the safe side we follow Microsoft's recommended practice of flushing the instruction cache after performing the patch by calling FlushInstructionCache. This is to avoid nasty things from happening if the patched code has already been pre-fetched by (one of) the CPU.


Now we just have to figure out where to patch and what to patch it with. We have covered the details of how dynamic and message methods work in earlier posts. Looking at the source of TProgressBar and confirmed by peeking with the debugger, there are no dynamic or message method overrides at all in this class. This is good news because it means that the DynamicTable pointer in the VMT is nil and this makes it much easier to perform the patch. So now we know where to patch - the DMT slot in the VMT of TProgressBar. To keep things simple in the initial version we use the vmtDynamicTable constant exported by the System unit.

{ Virtual method table entries }
const
// ...
vmtDynamicTable = -48;

Given a TProgressBar class reference we can calculate the address of the DMT slot in the VMT by using this code:

var
OriginalDmt: PDWORD;
begin
OriginalDmt := PDWORD(TProgressBar);
Inc(OriginalDmt, vmtDynamicTable div SizeOf(DWORD));
if OriginalDmt^ = 0 then // Assert that there is no existing Dmt

Now we have to find what to replace the nil DMT pointer with. We could try to build a DMT table by hand by using the tables we documented here, but it would be wasted effort. The compiler is much better than us building VMTs and DMTs, so we can just use the TProgressBarVistaFix from the previous post.

type
TProgressBarVistaFix = class(TProgressBar)
private
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message
WM_ERASEBKGND;
end;

procedure TProgressBarVistaFix.WMEraseBkgnd(var Message: TWmEraseBkgnd);
begin
DefaultHandler(Message);
end;

We can get to the DMT pointer for this new class in the same way and use it to overwrite the (previously nil) DMT pointer in the TProgressBar class. This is my initial patching routine:

procedure PatchTProgressBarDMT;
var
OriginalDmt, NewDmt: PDWORD;
begin
OriginalDmt := PDWORD(TProgressBar);
Inc(OriginalDmt, vmtDynamicTable div SizeOf(DWORD));
if OriginalDmt^ = 0 then // Assert that there is no existing Dmt
begin
NewDmt := PDWORD(TProgressBarVistaFix);
Inc(NewDmt, vmtDynamicTable div SizeOf(DWORD));
PatchCodeDWORD(OriginalDmt, NewDmt^);
end;
end;

Testing this code shows that it works and that the WM_ERASEBKFND handler is called and the flicker is gone on Vista. However, I'm not too satisfied with the code, so I refactor it into a separate general unit - this time using the HVVMT unit and the PVmt record pointer.

unit HVPatching;

interface

uses
Windows;

procedure PatchCodeDWORD(Code: PDWORD; Value: DWORD);

procedure ReplaceClassDmt(TargetClass, SourceClass: TClass);

implementation

uses
HVVMT;

procedure PatchCodeDWORD(Code: PDWORD; Value: DWORD);
// Self-modifying code - change one DWORD in the code segment
var
RestoreProtection, Ignore: DWORD;
begin
if VirtualProtect(Code, SizeOf(Code^), PAGE_EXECUTE_READWRITE,
RestoreProtection) then
begin
Code^ := Value;
VirtualProtect(Code, SizeOf(Code^), RestoreProtection, Ignore);
FlushInstructionCache(GetCurrentProcess, Code, SizeOf(Code^));
end;
end;

procedure ReplaceClassDmt(TargetClass, SourceClass: TClass);
begin
Assert(Assigned(TargetClass) and Assigned(SourceClass));
PatchCodeDWORD(@GetVmt(TargetClass).DynamicTable,
DWORD(GetVmt(SourceClass).DynamicTable));
end;

end.

Then we can use it like this:

initialization
ReplaceClassDmt(TProgressBar, TProgressBarVistaFix);
end.

In this case we were lucky. In other cases the patched class may already have one or more dynamic or message methods - so that there will already be a DMT pointer in the VMT. In this case we must play the compiler and manually allocate a new DMT with one extra entry, copy the existing DMT indicies and method code pointers and finally patch in the new dynamic method index or message-id and the address of the hook routine. This is quite a bit more complex, but if there is interest in digging further down we might revisit this later.



Copyright © 2004-2007 by Hallvard Vassbotn