Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2010-07

mising ansi string ref increase

13 messages · 7 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Martin

I have an odd case (bug ?)
But I am unable to reproduce on a simple example.

Debugger output, and assembler both suggests it's in the compilation. fpc from trunk a few weeks ago. using -OpPENTIUMM -O1

one procedure is declared as
     procedure SetFoldState(const AValue: String);
another one calls this as follows
     if FPendingFoldState  '' then
       SetFoldState(FPendingFoldState);

FPendingFoldState is a variable (String) of the object (both methods belong to the same object too)

Now in SetFoldstate is a line:
   FPendingFoldState:='';

and after this AValue becomes corrupt

The assembler of the calling code (from -al)
# [6541] if FPendingFoldState '' then
movl -4(%ebp),%eax
movl 1352(%eax),%eax
testl %eax,%eax
je .Lj12594
.Ll3371:
# [6542] SetFoldState(FPendingFoldState);
movl -4(%ebp),%eax
movl 1352(%eax),%edx
movl -4(%ebp),%eax
call SYNEDIT_TCUSTOMSYNEDIT_$__SETFOLDSTATE$ANSISTRING .Lj12594:

There is no ansistring inc ref (both methods are in the same file, and yes {$H+}

Trying to reproduce in a smaller example did not bring results....

Anyone any idea, if there s any code that could cause such an "optimization" ?

Martin

Reply by email

Martin
to Martin

Ok I reproduced it. (compiled with -gh -gt -O1 => but I am not sure it matters

Question: Is it some wrong doing of me? or shall i report it as bug?

In Foo, "s" is supposed to be a copy of "x" => the string should have a ref count of 2, and the modification of x, should make a copy of the string.
afaik the output should be "a" => but it is "X"

You can also set x:='' => which will be random in output
program Project1;
{$mode objfpc}{$H+}
var
   x: String;
procedure Foo(const s: String);
begin
   x[1]:='X';  //  x:='';
   writeln(s);
end;
procedure Bar;
begin
   SetLength(x,1);
   x[1]:= 'a';
end;
{$R *.res}
begin
   Bar;
   Foo(x);
   readln;
end.
Martin wrote 49 lines
I have an odd case (bug ?) But I am unable to reproduce on a simple example. Debugger output, and assembler both suggests it's in the compilation. fpc from trunk a few weeks ago. using -OpPENTIUMM -O1 one procedure is declared as procedure SetFoldState(const AValue: String); another one calls this as follows if FPendingFoldState '' then SetFoldState(FPendingFoldState); FPendingFoldState is a variable (String) of the object (both methods belong to the same object too) Now in SetFoldstate is a line: FPendingFoldState:=''; and after this AValue becomes corrupt The assembler of the calling code (from -al) # [6541] if FPendingFoldState '' then movl -4(%ebp),%eax movl 1352(%eax),%eax testl %eax,%eax je .Lj12594 .Ll3371: # [6542] SetFoldState(FPendingFoldState); movl -4(%ebp),%eax movl 1352(%eax),%edx movl -4(%ebp),%eax call SYNEDIT_TCUSTOMSYNEDIT_$__SETFOLDSTATE$ANSISTRING .Lj12594: There is no ansistring inc ref (both methods are in the same file, and yes {$H+} Trying to reproduce in a smaller example did not bring results.... Anyone any idea, if there s any code that could cause such an "optimization" ? Martin _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Florian Klaempfl
to Martin
Martin wrote 24 lines
Ok I reproduced it. (compiled with -gh -gt -O1 => but I am not sure it matters Question: Is it some wrong doing of me? or shall i report it as bug? In Foo, "s" is supposed to be a copy of "x" => the string should have a ref count of 2, and the modification of x, should make a copy of the string. afaik the output should be "a" => but it is "X" You can also set x:='' => which will be random in output program Project1; {$mode objfpc}{$H+} var x: String; procedure Foo(const s: String); begin x[1]:='X'; // x:=''; writeln(s); end;

This should not compile. The string is declared const, please fill a bug report.

Reply by email

Paul Ishenin
to Florian Klaempfl
Florian Klaempfl wrote 11 lines
> var > x: String; > > procedure Foo(const s: String); > begin > x[1]:='X'; // x:=''; > writeln(s); > end; This should not compile. The string is declared const, please fill a bug report.

why it should not? 's' is declared as const but not the 'x'.

Best regards,
Paul Ishenin.

Reply by email

Sergei Gorelkin
to Martin: I have an odd case (bug ?) But I am unable to reproduce on a simple example. Debugger…

Martin пишет:

Anyone any idea, if there s any code that could cause such an "optimization" ?

This is by design. 'const' modifier on ansistring and other 'managed' type arguments instucts the compiler to omit refcount changes, yielding a faster code. At the same time it prohibits direct modification to the argument, but nothing can be done if you modify another location that aliases the argument.
If you need proper refcounting, you should pass the argument by value (i.e. without 'const' modifier).

Regards,
Sergei

Reply by email

Martin
to Sergei Gorelkin
Sergei Gorelkin wrote 12 lines
Martin пишет: > > Anyone any idea, if there s any code that could cause such an > "optimization" ? > This is by design. 'const' modifier on ansistring and other 'managed' type arguments instucts the compiler to omit refcount changes, yielding a faster code. At the same time it prohibits direct modification to the argument, but nothing can be done if you modify another location that aliases the argument. If you need proper refcounting, you should pass the argument by value (i.e. without 'const' modifier).

So, no need to report as bug then?

Reply by email

Martin
to Martin
Martin wrote 15 lines
On 22/07/2010 09:57, Sergei Gorelkin wrote: > Martin пишет: >> >> Anyone any idea, if there s any code that could cause such an >> "optimization" ? >> > This is by design. 'const' modifier on ansistring and other 'managed' > type arguments instucts the compiler to omit refcount changes, > yielding a faster code. At the same time it prohibits direct > modification to the argument, but nothing can be done if you modify > another location that aliases the argument. > If you need proper refcounting, you should pass the argument by value > (i.e. without 'const' modifier). So, no need to report as bug then?

Btw, just an idea.

A possibility (probably quicker than inc-string-ref) would be: In the case that other (none local) strings are used (and modified) inside such a function/procedure then they are compared (just the pointer) to the const argument. If equal, then inc-ref can still be called.

Optimization (later) could spot localization of such checks => if the other string is modified only in a certain spot, (if something) then checks could be executed only if the conditional block was entered.

Martin

Reply by email

Jonas Maebe
to Martin: So, no need to report as bug then?
Martin wrote 5 lines
On 22/07/2010 09:57, Sergei Gorelkin wrote: > This is by design. 'const' modifier on ansistring and other 'managed' type arguments instucts the compiler to omit refcount changes, yielding a faster code. At the same time it prohibits direct modification to the argument, but nothing can be done if you modify another location that aliases the argument. > If you need proper refcounting, you should pass the argument by value (i.e. without 'const' modifier). So, no need to report as bug then?

Indeed, Sergei is correct. In a language like Pascal, there is no way for the compiler to ensure that the constness of parameters is completely observed. It's more like a hint of the programmer to the code generator ("the values passed to this parameter will not changed, so you can optimize however you like based on that assumption") than a semantic condition for the compiler to guarantee ("make sure that I do not change values passed to this parameter in any way").

Jonas

Reply by email

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 16 lines
On 22 Jul 2010, at 12:06, Martin wrote: > On 22/07/2010 09:57, Sergei Gorelkin wrote: >> This is by design. 'const' modifier on ansistring and other 'managed' type arguments instucts the compiler to omit refcount changes, yielding a faster code. At the same time it prohibits direct modification to the argument, but nothing can be done if you modify another location that aliases the argument. >> If you need proper refcounting, you should pass the argument by value (i.e. without 'const' modifier). > > So, no need to report as bug then? Indeed, Sergei is correct. In a language like Pascal, there is no way for the compiler to ensure that the constness of parameters is completely observed. It's more like a hint of the programmer to the code generator ("the values passed to this parameter will not changed, so you can optimize however you like based on that assumption") than a semantic condition for the compiler to guarantee ("make sure that I do not change values passed to this parameter in any way").

For what it is worth: Delphi behaves the same as FPC.

Michael.

Reply by email

Martin
to Michael Van Canneyt
Michael Van Canneyt wrote 28 lines
On Thu, 22 Jul 2010, Jonas Maebe wrote: > > On 22 Jul 2010, at 12:06, Martin wrote: > >> On 22/07/2010 09:57, Sergei Gorelkin wrote: >>> This is by design. 'const' modifier on ansistring and other >>> 'managed' type arguments instucts the compiler to omit refcount >>> changes, yielding a faster code. At the same time it prohibits >>> direct modification to the argument, but nothing can be done if you >>> modify another location that aliases the argument. >>> If you need proper refcounting, you should pass the argument by >>> value (i.e. without 'const' modifier). >> >> So, no need to report as bug then? > > Indeed, Sergei is correct. In a language like Pascal, there is no way > for > the compiler to ensure that the constness of parameters is completely > observed. It's more like a hint of the programmer to the code generator > ("the values passed to this parameter will not changed, so you can > optimize however you like based on that assumption") than a semantic > condition for the compiler to guarantee ("make sure that I do not change > values passed to this parameter in any way"). For what it is worth: Delphi behaves the same as FPC.

I saw the error in my thinking, after Jonas (re-) explained the meaning of "const".

and I guess it applies to other types to (as long as they are passed by reference): e.g records are likely to see changes too...

Reply by email

Sergei Gorelkin
to Martin
Martin wrote 6 lines
I saw the error in my thinking, after Jonas (re-) explained the meaning of "const". and I guess it applies to other types to (as long as they are passed by reference): e.g records are likely to see changes too...

Indeed. I was initially not completely correct, and should have said: the 'const' modifier prevents creation of the local copy of the argument. The exact way of creating local copy depends on the argument type: for reference-counted types, it is done by manipulating the refcount, other types like shortstrings use a plain copy, etc.

Regards,
Sergei

Reply by email