On Wed, May 2, 2012 at 8:33 PM, Seth Ladd <
seth...@google.com> wrote:
> Hi Florian,
>
> Can you help explain why canonicalization costs are different for the
> following two cases? (I hope I understood your point below...)
I'm not Florian, but I'll give it a shot :)
>
> class Point {
> final num x, y;
> const Point(this.x, this.y);
> }
>
> main() {
> var pNew = new Point(1,2);
> var pConst = const Point(1,2);
> }
Nothing in this simple example prevents the compiler from recognizing
"new Point(1,2)" and creating a constant from in at compile time, if
the language was so designed. You need a more complex example to show
the problem:
main() {
for (int i = 0; i < 4; i++) {
var pNew = new Point(i, i+1);
print(pNew);
}
var pConst = const Point(1,2);
pConst = const Point(2,3);
}
In this case, the arguments to the Point constructor aren't
compile-time constants. That means that to canonicalize the result of
"new Point(i,i+1)", you have to do it at runtime, when you know the
value of "i".
That's where Florian says you need to remember all instances of Point
to be able to dynamically find one, if any, that matches the inputs to
the current constructor call.
As Dart is designed now, there is no such data structures at runtime.
All compile-time constants are created using "const" instead of "new",
and they are created and canonicalized at *compile time*. That's why
"const" constructor calls must only have compile-time constants as
arguments, and why the constructors can't do anything except
initialize fields - it must be done without any code execution.
At runtime, you can only use "new", and it always creates a new object
(for const constructors at least).
So, runtime canonicalization requires a runtime overhead, both in time
whenever you create a new object, and in memory to make it possible to
find an already existing canonical object. The memory overhead is
constantly there, since you never know if your program will create
another object. Dart is designed to not have that overhead.
The compile-time canonicalization has a similar overhead, but it's
static - constrained by the syntax of the program, not the execution,
so each "const" constructor call generates only one constant, not one
every time it's executed - and the data structure can be dropped when
the phase is over, or at least when compilation is over. It only
affects compile-time, not execution time.
Hope this makes sense.
/L
--
Lasse R.H. Nielsen
l...@google.com
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 København K -
Denmark - CVR nr. 28 86 69 84