point2D(xc, yc) { 2 method x { xc } method y { yc } 4 method length { (x ∗ x + y ∗ y).sqrt } } Figure 1: A simple immutable point object in Grace. Note that there are no explicit fields; instead, the methods x and y refer to (and thus capture) the parameters of the class. successor function in a continuation-passing style. When the stack fills up, an exception-handler (the trampoline) restarts the computation. They report that the function-calling tech- nique introduces far more overhead (250%) than the case + continue technique (50%) [Ibid., Fig 13]. They do not com- pare two other “obvious” alternatives. The first (currently adopted by minigrace), is to use an exception to represent ”u 2 fu 4 6 8 } 10 ”u fu 12 class point2D(xc, yc) { 2 method x { xc } method y { yc } 4 method length { (x ∗ x + y ∗ y).sqrt } } Figure 1: A simple immutable point object in Grace. Note that there are no explicit fields; instead, the methods x and y refer to (and thus capture) the parameters of the class. method point2D(xc, yc) { 2 object { method x { xc } 4 method y { yc } method length { (x ∗ x + y ∗ y).sqrt } 6 } } Figure 2: A simple immutable point object in Grace. Note that there are no ”u 2 fu 4 6 8 } 10 ”u fu 12 ≡
implicit 4 • Explicit fields are possible too: class point2D(xc, yc) { 2 method x { xc } method y { yc } 4 method length { (x ∗ x + y ∗ y).sqrt } } Figure 1: A simple immutable point object in Grace. Note that there are no explicit fields; instead, the methods x and y refer to (and thus capture) the parameters of the class. successor function in a continuation-passing style. When the stack fills up, an exception-handler (the trampoline) restarts the computation. They report that the function-calling tech- nique introduces far more overhead (250%) than the case + continue technique (50%) [Ibid., Fig 13]. They do not com- ”u 2 fu 4 6 8 } 10 ”u fu Figure 1: A simple immutable point object in Grace. Note that there are no explicit fields; instead, the methods x and y refer to (and thus capture) the parameters of the class. method point2D(xc, yc) { 2 object { method x { xc } 4 method y { yc } method length { (x ∗ x + y ∗ y).sqrt } 6 } } Figure 2: A simple immutable point object in Grace. Note that there are no explicit fields; instead, the methods x and y refer to (and thus capture) the parameters of the class. class point2D(xc, yc) { 2 def x is public = xc def y is public = yc 4 method length { (x ∗ x + y ∗ y).sqrt } } Figure 3: A simple immutable point object in Grace. Note that there are no explicit fields; instead, the methods x and y refer to (and thus capture) the 8 } 2. Start show enco illus cons tions data, tions the o In the c =
implementor’s toolkit - Objects can have data & function attributes - Functions be executed with the owning object — or any other object — as self - Prototype chain allows objects to share attributes 5
Don’t treat JavaScript as an assembly language … • Instead, use JavaScript objects to implement Grace objects • Use JavaScript’s method dispatch rather than “rolling our own” 6
object must distinguish between method request object.request( ) and field access object.field • JavaScript getters hijack the field-access syntax to request parameterless methods object.request 9
access and method request • The client does not (and should not) know how an object chooses to implement an attribute • Should we abstract over the distinction between fields and methods ourselves, or use JavaScript getters (and setters) to do this for us? 10
points by hand - Benchmarked: ‣ access: request & execute length on 20k points ‣ construct 20k points ‣ access + construct: build 20k new points based on 20k old points ‣ modify coordinates of 20k points • Run in Chrome 50.0.2661 on MacOS 10.11.3 12
1 P0R 1A0 P0R 1A1 P0R 1G 1 P1R 1A0 P1R 1A1 P1R 1G 1 Time for 20k ops / ms Access 0.1 1 10 100 1000 Time for 20k ops / ms Not using prototypes costs ~3x
1 P0R 1A0 P0R 1A1 P0R 1G 1 P1R 1A0 P1R 1A1 P1R 1G 1 Time for 20k ops / ms Access + Construct 0 1 10 100 Time for 20k ops / ms Not surprising: prototypes are much faster
function() { return xc; } ; 4 this.y = function() { return yc; } ; this.length = function() { 6 return Math.sqrt((this.x() ∗ this.x()) + (this.y() ∗ this.y())); 8 } ; } Figure 4: A possible Javascript implementation of Figure 1. 2. Experiment Design Starting with the Grace code for a 2-dimensional point, shown in Figure 1, we designed eight different JavaScript encodings and generated them by hand. In the first encoding, illustrated in Figure 4, a Grace class compiles to a JavaScript constructor that returns an object. This object contains func- 10 ”use strict”; function P1R1A1(xc, yc) { 12 this.xc = xc; this.yc = yc; } 14 P1R1A1.prototype.x = function() { return this.xc; } ; 16 P1R1A1.prototype.y = function() { return this.yc; } ; P1R1A1.prototype.length = function() { 18 return Math.sqrt((this.x() ∗ this.x()) + (this.y() ∗ this.y())) } ; Figure 5: An alternative Javascript implementation of Figure 1, which