View mode: basic / threaded / horizontal-split · Log in · Help
October 23, 2012
Structs, Speed and refs.
Hey everybody!

A bit of background; I'm porting some code over from D1 to D2 and 
I ran into a bit of a problem. I have a bunch of code that looks 
something like this:

class Bar : Other {
  override void func(ref LargeStruct st) {}
}

Bar bar;
LargeStruct foo, too;
bar.func(foo - too);

This compiles just fine in D1 but no longer in D2. Because the 
temp created by "foo - too" is not a lvalue apparently. I don't 
want to remove the "ref" storage type because i still want it to 
be fast. And I rather have neater looking code vs:

LargeStruct foo, too, temp;
temp = foo - too;
bar.func(temp);

One solution is to turn "in" structs into pass by reference, eg 
const ref, but not require lvalue semantics at the call site?

Cheers, Jakob.
October 23, 2012
Re: Structs, Speed and refs.
Hi,

First of all, I think there is no difference in speed between

LargeStruct foo, too, temp;
temp = foo - too;
bar.func(temp);

and with func without ref.

How looks your opBinary(Right) method?

For eg. this works for me:

struct LargeStruct {
	int x;
	
	auto ref opBinary(string op)(LargeStruct rhs) if (op == "-") {		
		this.x = this.x - rhs.x;
		return this;
	}
}

class Bar {
  void func(ref LargeStruct st) {}
}


void main(string[] args)
{
	Bar bar = new Bar();
	LargeStruct foo, too;
	bar.func(foo - too);
}

However this will modify foo struct.


On Tuesday, 23 October 2012 at 09:44:06 UTC, Jakob Bornecrantz 
wrote:
> Hey everybody!
>
> A bit of background; I'm porting some code over from D1 to D2 
> and I ran into a bit of a problem. I have a bunch of code that 
> looks something like this:
>
> class Bar : Other {
>   override void func(ref LargeStruct st) {}
> }
>
> Bar bar;
> LargeStruct foo, too;
> bar.func(foo - too);
>
> This compiles just fine in D1 but no longer in D2. Because the 
> temp created by "foo - too" is not a lvalue apparently. I don't 
> want to remove the "ref" storage type because i still want it 
> to be fast. And I rather have neater looking code vs:
>
> LargeStruct foo, too, temp;
> temp = foo - too;
> bar.func(temp);
>
> One solution is to turn "in" structs into pass by reference, eg 
> const ref, but not require lvalue semantics at the call site?
>
> Cheers, Jakob.
October 23, 2012
Re: Structs, Speed and refs.
On Tuesday, 23 October 2012 at 10:36:11 UTC, Daniel Kozák wrote:
> Hi,
>
> First of all, I think there is no difference in speed between
>
> LargeStruct foo, too, temp;
> temp = foo - too;
> bar.func(temp);
>
> and with func without ref.

That doesn't seem to be the case, as at least DMD always copies
to the stack. Even if I change the function to have the struct
as a unused local variable it still copies.

void example(LargeStruct t, Bar bar)
{
   bar.func(t);
}

with ref:
Dump of assembler code for function 
_D7example4testFS7example11LargeStructC7example3BarZv:
   0x0000000000425ee0 <+0>:	push   %rbp
   0x0000000000425ee1 <+1>:	mov    %rsp,%rbp
   0x0000000000425ee4 <+4>:	sub    $0x10,%rsp
   0x0000000000425ee8 <+8>:	lea    0x10(%rbp),%rsi
   0x0000000000425eec <+12>:	mov    (%rdi),%rax
   0x0000000000425eef <+15>:	rex.W callq *0x30(%rax)
   0x0000000000425ef3 <+19>:	mov    %rbp,%rsp
   0x0000000000425ef6 <+22>:	pop    %rbp
   0x0000000000425ef7 <+23>:	retq

without ref:
Dump of assembler code for function 
_D7example4testFS7example11LargeStructC7example3BarZv:
   0x0000000000425ee0 <+0>:	push   %rbp
   0x0000000000425ee1 <+1>:	mov    %rsp,%rbp
   0x0000000000425ee4 <+4>:	sub    $0x10,%rsp
   0x0000000000425ee8 <+8>:	lea    0x208(%rbp),%rsi
   0x0000000000425eef <+15>:	mov    $0x40,%ecx
   0x0000000000425ef4 <+20>:	pushq  (%rsi)
   0x0000000000425ef6 <+22>:	sub    $0x8,%rsi
   0x0000000000425efa <+26>:	loop   0x425ef4 
<_D7example4testFS7example11LargeStructC7example3BarZv+20>
   0x0000000000425efc <+28>:	mov    (%rdi),%rax
   0x0000000000425eff <+31>:	rex.W callq *0x30(%rax)
   0x0000000000425f03 <+35>:	add    $0x200,%rsp
   0x0000000000425f0a <+42>:	mov    %rbp,%rsp
   0x0000000000425f0d <+45>:	pop    %rbp
   0x0000000000425f0e <+46>:	retq


>
> How looks your opBinary(Right) method?
>
> For eg. this works for me:
>
> struct LargeStruct {
> 	int x;
> 	
> 	auto ref opBinary(string op)(LargeStruct rhs) if (op == "-") 
> {		
> 		this.x = this.x - rhs.x;
> 		return this;
> 	}
> }
>
> class Bar {
>   void func(ref LargeStruct st) {}
> }
>
>
> void main(string[] args)
> {
> 	Bar bar = new Bar();
> 	LargeStruct foo, too;
> 	bar.func(foo - too);
> }
>
> However this will modify foo struct.

Since this is D1 code being ported I'm currently using
opSub. I tried changing your code to opSub and I got the
same error as with mine. Your example should probably be
an error. I'm not saying I was right in doing what I did.
The point of the post was to improve D.

Cheers, Jakob.
October 23, 2012
Re: Structs, Speed and refs.
On Tuesday, 23 October 2012 at 09:44:06 UTC, Jakob Bornecrantz 
wrote:
> One solution is to turn "in" structs into pass by reference, eg 
> const ref, but not require lvalue semantics at the call site?

And here we go again - missing rvalue-to-const-ref propagation. 
Check out 
http://forum.dlang.org/thread/yhnbcocwxnbutylfeoxi@forum.dlang.org
Top | Discussion index | About this forum | D home