Thread overview | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 27, 2011 null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
I have compiled this little D2 program: int[] foo() { return []; } int[] bar() { return null; } void main() {} Using DMD 2.052, dmd -O -release -inline test2.d This is the asm of the two functions: _D5test23fooFZAi comdat L0: push EAX mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ push 0 push EAX call near ptr __d_arrayliteralT mov EDX,EAX add ESP,8 pop ECX xor EAX,EAX ret _D5test23barFZAi comdat xor EAX,EAX xor EDX,EDX ret Is this expected and desired? Isn't it better to compile the foo() as bar()? Bye, bearophile |
March 27, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile Wrote:
> I have compiled this little D2 program:
>
>
> int[] foo() {
> return [];
> }
> int[] bar() {
> return null;
> }
> void main() {}
>
>
>
> Using DMD 2.052, dmd -O -release -inline test2.d
>
> This is the asm of the two functions:
>
> _D5test23fooFZAi comdat
> L0: push EAX
> mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
> push 0
> push EAX
> call near ptr __d_arrayliteralT
> mov EDX,EAX
> add ESP,8
> pop ECX
> xor EAX,EAX
> ret
>
> _D5test23barFZAi comdat
> xor EAX,EAX
> xor EDX,EDX
> ret
>
> Is this expected and desired? Isn't it better to compile the foo() as bar()?
>
> Bye,
> bearophile
[] is not null, it's an array of 0 elements, what is done exactly. edx points to the allocated array.
|
March 27, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | Kagamin:
> [] is not null, it's an array of 0 elements, what is done exactly. edx points to the allocated array.
I don't understand what you say. I think the caller of foo() and bar() receive the same thing, two empty registers. I think that cast(int[])null and cast(int[])[] are the same thing for D.
void main() {
assert(cast(int[])null == cast(int[])null);
auto a1 = cast(int[])null;
a1 ~= 1;
auto a2 = 1 ~ cast(int[])null;
}
Bye,
bearophile
|
March 27, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 2011-03-27 11:42, bearophile wrote:
> Kagamin:
> > [] is not null, it's an array of 0 elements, what is done exactly. edx points to the allocated array.
>
> I don't understand what you say. I think the caller of foo() and bar()
> receive the same thing, two empty registers. I think that cast(int[])null
> and cast(int[])[] are the same thing for D.
>
> void main() {
> assert(cast(int[])null == cast(int[])null);
> auto a1 = cast(int[])null;
> a1 ~= 1;
> auto a2 = 1 ~ cast(int[])null;
> }
What I would _expect_ the difference between a null array and an empty one to be would be that the null one's ptr property would be null, whereas the empty one wouldn't be. But dmd treats them pretty much the same. empty returns true for both. You can append to both. The null one would be a guaranteed memory reallocation when you append to it whereas the empty one may not be, but their behavior is almost identical.
How that affects the generated assembly code, I don't know. Particularly if you're compiling with -inline and and -O, the compiler can likely make assumptions about null that it can't make about [], since it probably treats [] more generally without worrying about the fact that it happens to be empty as far as optimizations go - that and there _is_ a semantic difference between null and [] if you're messing with the ptr property, so Walter may think that it's best for null to not be turned into the same thing as [] automatically.
- Jonathan M Davis
|
March 27, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | Jonathan M Davis:
> the compiler can likely make assumptions about null that it can't make about [], since it probably treats [] more generally without worrying about the fact that it happens to be empty as far as optimizations go - that and there _is_ a semantic difference between null and [] if you're messing with the ptr property, so Walter may think that it's best for null to not be turned into the same thing as [] automatically.
Thank you for your answer. I have added a low-priority enhancement request.
Bye,
bearophile
|
March 28, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile Wrote:
> Kagamin:
>
> > [] is not null, it's an array of 0 elements, what is done exactly. edx points to the allocated array.
>
> I don't understand what you say. I think the caller of foo() and bar() receive the same thing, two empty registers. I think that cast(int[])null and cast(int[])[] are the same thing for D.
That's a mistake.
Well, if there's no differnce for you, you can use either of them. What's the problem?
|
March 28, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sun, 27 Mar 2011 09:37:47 -0400, bearophile <bearophileHUGS@lycos.com> wrote:
> I have compiled this little D2 program:
>
>
> int[] foo() {
> return [];
> }
> int[] bar() {
> return null;
> }
> void main() {}
>
>
>
> Using DMD 2.052, dmd -O -release -inline test2.d
>
> This is the asm of the two functions:
>
> _D5test23fooFZAi comdat
> L0: push EAX
> mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
> push 0
> push EAX
> call near ptr __d_arrayliteralT
> mov EDX,EAX
> add ESP,8
> pop ECX
> xor EAX,EAX
> ret
>
> _D5test23barFZAi comdat
> xor EAX,EAX
> xor EDX,EDX
> ret
>
> Is this expected and desired? Isn't it better to compile the foo() as bar()?
Probably. The runtime that allocates an array looks like this (irrelevant parts collapsed):
extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...)
{
auto sizeelem = ti.next.tsize(); // array element size
void* result;
...
if (length == 0 || sizeelem == 0)
result = null;
else
{
...
}
return result;
}
So essentially, you are getting the same thing, but using [] is slower.
-Steve
|
March 28, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer:
> So essentially, you are getting the same thing, but using [] is slower.
It seems I was right then, thank you and Kagamin for the answers.
Bye,
bearophile
|
April 01, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Mon, 28 Mar 2011 17:54:29 +0100, bearophile <bearophileHUGS@lycps.com> wrote:
> Steven Schveighoffer:
>
>> So essentially, you are getting the same thing, but using [] is slower.
>
> It seems I was right then, thank you and Kagamin for the answers.
This may be slightly OT but I just wanted to raise the point that conceptually it's nice to be able to express (exists but is empty) and (does not exist). Pointers/references have null as a (does not exist) "value" and this is incredibly useful. Try doing the same thing with 'int' .. it requires you either use int* or pass an additional boolean to indicate existence.. yuck.
I'd suggest if someone types '[]' they mean (exists but is empty) and if they type 'null' they mean (does not exist) and they may be relying on the .ptr value to differentiate these cases, which is useful. If you're not interested in the difference, and you need performance, you simply use 'null'. Everybody is happy. :)
R
|
April 01, 2011 Re: null Vs [] return arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan Heath:
> conceptually it's nice to be able to express (exists but is empty) and (does not exist).
You may want to express that, but for the implementation of the language those two situations are the same, because in the [] literal the ptr is null. So I think it's better for the programmer to not differentiate the two situations, because they are not different. If the programmer tells them apart, he/she is doing something bad in D, creating a false illusion.
Bye,
bearophile
|
Copyright © 1999-2021 by the D Language Foundation