| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 // Test allocation sinking optimization. | |
| 5 // VMOptions=--optimization-counter-threshold=10 --no-use-osr --no-background-co
mpilation | |
| 6 | |
| 7 import 'dart:typed_data'; | |
| 8 import 'package:expect/expect.dart'; | |
| 9 | |
| 10 class Point { | |
| 11 var x, y; | |
| 12 | |
| 13 Point(this.x, this.y); | |
| 14 | |
| 15 operator *(other) { | |
| 16 return x * other.x + y * other.y; | |
| 17 } | |
| 18 } | |
| 19 | |
| 20 class C { | |
| 21 var p; | |
| 22 C(this.p); | |
| 23 } | |
| 24 | |
| 25 class Pointx4 { | |
| 26 var x, y; | |
| 27 | |
| 28 Pointx4(this.x, this.y); | |
| 29 | |
| 30 operator *(other) { | |
| 31 return x * other.x + y * other.y; | |
| 32 } | |
| 33 } | |
| 34 | |
| 35 class Cx4 { | |
| 36 var p; | |
| 37 Cx4(this.p); | |
| 38 } | |
| 39 | |
| 40 class D { | |
| 41 var p; | |
| 42 D(this.p); | |
| 43 } | |
| 44 | |
| 45 // Class that is used to capture materialized Point object with * operator. | |
| 46 class F { | |
| 47 var p; | |
| 48 var val; | |
| 49 | |
| 50 F(this.p); | |
| 51 | |
| 52 operator *(other) { | |
| 53 Expect.isTrue(other is Point); | |
| 54 Expect.equals(42.0, other.x); | |
| 55 Expect.equals(0.5, other.y); | |
| 56 | |
| 57 if (val == null) { | |
| 58 val = other; | |
| 59 } else { | |
| 60 Expect.isTrue(identical(val, other)); | |
| 61 } | |
| 62 | |
| 63 return this.p * other; | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 test1(c, x, y) { | |
| 68 var a = new Point(x - 0.5, y + 0.5); | |
| 69 var b = new Point(x + 0.5, y + 0.8); | |
| 70 var d = new Point(c.p * a, c.p * b); | |
| 71 return d * d; | |
| 72 } | |
| 73 | |
| 74 test1x4(c, x, y, z, w) { | |
| 75 var a = new Pointx4(x - z, y + w); | |
| 76 var b = new Pointx4(x + w, y + z); | |
| 77 var d = new Pointx4(c.p * a, c.p * b); | |
| 78 return d * d; | |
| 79 } | |
| 80 | |
| 81 effects() { | |
| 82 // This function should not be inlinable. | |
| 83 try {} catch (e) {} | |
| 84 } | |
| 85 | |
| 86 testForwardingThroughEffects(c, x, y) { | |
| 87 var a = new Point(x - 0.5, y + 0.5); | |
| 88 var b = new Point(x - 0.5, y - 0.8); | |
| 89 var d = new Point(c.p * a, c.p * b); | |
| 90 // Effects can't affect neither a, b, nor d because they do not escape. | |
| 91 effects(); | |
| 92 effects(); | |
| 93 return ((a == null) ? 0.0 : 0.1) + (d * d); | |
| 94 } | |
| 95 | |
| 96 testIdentity(x) { | |
| 97 var y = new Point(42.0, 0.5); | |
| 98 var z = y; | |
| 99 return x * y + x * z; | |
| 100 } | |
| 101 | |
| 102 class PointP<T> { | |
| 103 var x, y; | |
| 104 | |
| 105 PointP(this.x, this.y); | |
| 106 | |
| 107 operator *(other) { | |
| 108 return x * other.x + y * other.y; | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 foo2() => new PointP<int>(1, 3) * new PointP<num>(5, 6); | |
| 113 | |
| 114 class A<T> { | |
| 115 var x, y; | |
| 116 } | |
| 117 | |
| 118 foo3(x) { | |
| 119 // Test materialization of type arguments. | |
| 120 var a = new A<int>(); | |
| 121 a.x = x; | |
| 122 a.y = x; | |
| 123 if (x is int) return a.x + a.y; | |
| 124 Expect.isFalse(a is A<double>); | |
| 125 Expect.isTrue(a is A<int>); | |
| 126 Expect.isTrue(a is A); | |
| 127 return a.x - a.y; | |
| 128 } | |
| 129 | |
| 130 class WithFinal { | |
| 131 final _x; | |
| 132 WithFinal(this._x); | |
| 133 } | |
| 134 | |
| 135 testInitialValueForFinalField(x) { | |
| 136 new WithFinal(x); | |
| 137 } | |
| 138 | |
| 139 testFinalField() { | |
| 140 for (var i = 0; i < 100; i++) { | |
| 141 testInitialValueForFinalField(1); | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 class V { | |
| 146 var x = 0; | |
| 147 } | |
| 148 | |
| 149 test_vm_field() { | |
| 150 var obj; | |
| 151 inner() => obj.x = 42; | |
| 152 var a = new V(); | |
| 153 obj = a; | |
| 154 var t1 = a.x; | |
| 155 var t2 = inner(); | |
| 156 return a.x + t1 + t2; | |
| 157 } | |
| 158 | |
| 159 testVMField() { | |
| 160 Expect.equals(84, test_vm_field()); | |
| 161 for (var i = 0; i < 100; i++) test_vm_field(); | |
| 162 Expect.equals(84, test_vm_field()); | |
| 163 } | |
| 164 | |
| 165 class CompoundA { | |
| 166 var b; | |
| 167 CompoundA(this.b); | |
| 168 } | |
| 169 | |
| 170 class CompoundB { | |
| 171 var c; | |
| 172 CompoundB(this.c); | |
| 173 } | |
| 174 | |
| 175 class CompoundC { | |
| 176 var d; | |
| 177 var root; | |
| 178 CompoundC(this.d); | |
| 179 } | |
| 180 | |
| 181 class NoopSink { | |
| 182 const NoopSink(); | |
| 183 call(val) {} | |
| 184 } | |
| 185 | |
| 186 testCompound1() { | |
| 187 f(d, [sink = const NoopSink()]) { | |
| 188 var c = new CompoundC(d); | |
| 189 var a = new CompoundA(new CompoundB(c)); | |
| 190 sink(a); | |
| 191 return c.d; | |
| 192 } | |
| 193 | |
| 194 Expect.equals(0.1, f(0.1)); | |
| 195 for (var i = 0; i < 100; i++) f(0.1); | |
| 196 Expect.equals(0.1, f(0.1)); | |
| 197 Expect.equals( | |
| 198 0.1, | |
| 199 f(0.1, (val) { | |
| 200 Expect.isTrue(val is CompoundA); | |
| 201 Expect.isTrue(val.b is CompoundB); | |
| 202 Expect.isTrue(val.b.c is CompoundC); | |
| 203 Expect.isNull(val.b.c.root); | |
| 204 Expect.equals(0.1, val.b.c.d); | |
| 205 })); | |
| 206 } | |
| 207 | |
| 208 testCompound2() { | |
| 209 f(d, [sink = const NoopSink()]) { | |
| 210 var c = new CompoundC(d); | |
| 211 var a = new CompoundA(new CompoundB(c)); | |
| 212 c.root = a; | |
| 213 sink(a); | |
| 214 return c.d; | |
| 215 } | |
| 216 | |
| 217 Expect.equals(0.1, f(0.1)); | |
| 218 for (var i = 0; i < 100; i++) f(0.1); | |
| 219 Expect.equals(0.1, f(0.1)); | |
| 220 Expect.equals( | |
| 221 0.1, | |
| 222 f(0.1, (val) { | |
| 223 Expect.isTrue(val is CompoundA); | |
| 224 Expect.isTrue(val.b is CompoundB); | |
| 225 Expect.isTrue(val.b.c is CompoundC); | |
| 226 Expect.equals(val, val.b.c.root); | |
| 227 Expect.equals(0.1, val.b.c.d); | |
| 228 })); | |
| 229 } | |
| 230 | |
| 231 testCompound3() { | |
| 232 f(d, [sink = const NoopSink()]) { | |
| 233 var c = new CompoundC(d); | |
| 234 c.root = c; | |
| 235 sink(c); | |
| 236 return c.d; | |
| 237 } | |
| 238 | |
| 239 Expect.equals(0.1, f(0.1)); | |
| 240 for (var i = 0; i < 100; i++) f(0.1); | |
| 241 Expect.equals(0.1, f(0.1)); | |
| 242 Expect.equals( | |
| 243 0.1, | |
| 244 f(0.1, (val) { | |
| 245 Expect.isTrue(val is CompoundC); | |
| 246 Expect.equals(val, val.root); | |
| 247 Expect.equals(0.1, val.d); | |
| 248 })); | |
| 249 } | |
| 250 | |
| 251 testCompound4() { | |
| 252 f(d, [sink = const NoopSink()]) { | |
| 253 var c = new CompoundC(d); | |
| 254 c.root = c; | |
| 255 for (var i = 0; i < 10; i++) { | |
| 256 c.d += 1.0; | |
| 257 } | |
| 258 sink(c); | |
| 259 return c.d - 1.0 * 10; | |
| 260 } | |
| 261 | |
| 262 Expect.equals(1.0, f(1.0)); | |
| 263 for (var i = 0; i < 100; i++) f(1.0); | |
| 264 Expect.equals(1.0, f(1.0)); | |
| 265 Expect.equals( | |
| 266 1.0, | |
| 267 f(1.0, (val) { | |
| 268 Expect.isTrue(val is CompoundC); | |
| 269 Expect.equals(val, val.root); | |
| 270 Expect.equals(11.0, val.d); | |
| 271 })); | |
| 272 } | |
| 273 | |
| 274 main() { | |
| 275 var c = new C(new Point(0.1, 0.2)); | |
| 276 | |
| 277 // Compute initial values. | |
| 278 final x0 = test1(c, 11.11, 22.22); | |
| 279 var fc = new Cx4(new Pointx4( | |
| 280 new Float32x4(1.0, 1.0, 1.0, 1.0), new Float32x4(1.0, 1.0, 1.0, 1.0))); | |
| 281 final fx0 = test1x4( | |
| 282 fc, | |
| 283 new Float32x4(1.0, 1.0, 1.0, 1.0), | |
| 284 new Float32x4(1.0, 1.0, 1.0, 1.0), | |
| 285 new Float32x4(1.0, 1.0, 1.0, 1.0), | |
| 286 new Float32x4(1.0, 1.0, 1.0, 1.0)); | |
| 287 final y0 = testForwardingThroughEffects(c, 11.11, 22.22); | |
| 288 final z0 = testIdentity(c.p); | |
| 289 | |
| 290 // Force optimization. | |
| 291 for (var i = 0; i < 100; i++) { | |
| 292 test1(c, i.toDouble(), i.toDouble()); | |
| 293 test1x4( | |
| 294 fc, | |
| 295 new Float32x4(1.0, 1.0, 1.0, 1.0), | |
| 296 new Float32x4(1.0, 1.0, 1.0, 1.0), | |
| 297 new Float32x4(1.0, 1.0, 1.0, 1.0), | |
| 298 new Float32x4(1.0, 1.0, 1.0, 1.0)); | |
| 299 testForwardingThroughEffects(c, i.toDouble(), i.toDouble()); | |
| 300 testIdentity(c.p); | |
| 301 foo2(); | |
| 302 Expect.equals(10, foo3(5)); | |
| 303 } | |
| 304 Expect.equals(0.0, foo3(0.5)); | |
| 305 | |
| 306 // Test returned value after optimization. | |
| 307 final x1 = test1(c, 11.11, 22.22); | |
| 308 final y1 = testForwardingThroughEffects(c, 11.11, 22.22); | |
| 309 | |
| 310 // Test returned value after deopt. | |
| 311 final x2 = test1(new D(c.p), 11.11, 22.22); | |
| 312 final y2 = testForwardingThroughEffects(new D(c.p), 11.11, 22.22); | |
| 313 | |
| 314 Expect.equals(6465, (x0 * 100).floor()); | |
| 315 Expect.equals(6465, (x1 * 100).floor()); | |
| 316 Expect.equals(6465, (x2 * 100).floor()); | |
| 317 Expect.equals(x0, x1); | |
| 318 Expect.equals(x0, x2); | |
| 319 | |
| 320 Expect.equals(6008, (y0 * 100).floor()); | |
| 321 Expect.equals(6008, (y1 * 100).floor()); | |
| 322 Expect.equals(6008, (y2 * 100).floor()); | |
| 323 Expect.equals(y0, y1); | |
| 324 Expect.equals(y0, y2); | |
| 325 | |
| 326 // Test that identity of materialized objects is preserved correctly and | |
| 327 // no copies are materialized. | |
| 328 final z1 = testIdentity(c.p); | |
| 329 final z2 = testIdentity(new F(c.p)); | |
| 330 Expect.equals(z0, z1); | |
| 331 Expect.equals(z0, z2); | |
| 332 | |
| 333 testFinalField(); | |
| 334 testVMField(); | |
| 335 testCompound1(); | |
| 336 testCompound2(); | |
| 337 testCompound3(); | |
| 338 testCompound4(); | |
| 339 } | |
| OLD | NEW |