1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-ayle license that can be 3 // found in the LICENSE file. 4 5 // Flags: --allow-natives-syntax --track-fields --expose-gc 6 7 var global = Function('return this')(); 8 var verbose = 0; 9 10 function test(ctor_desc, use_desc, migr_desc) { 11 var n = 5; 12 var objects = []; 13 var results = []; 14 15 if (verbose) { 16 print(); 17 print("==========================================================="); 18 print("=== " + ctor_desc.name + 19 " | " + use_desc.name + " |--> " + migr_desc.name); 20 print("==========================================================="); 21 } 22 23 // Clean ICs and transitions. 24 %NotifyContextDisposed(); 25 gc(); gc(); gc(); 26 27 28 // create objects 29 if (verbose) { 30 print("-----------------------------"); 31 print("--- construct"); 32 print(); 33 } 34 for (var i = 0; i < n; i++) { 35 objects[i] = ctor_desc.ctor.apply(ctor_desc, ctor_desc.args(i)); 36 } 37 38 try { 39 // use them 40 if (verbose) { 41 print("-----------------------------"); 42 print("--- use 1"); 43 print(); 44 } 45 var use = use_desc.use1; 46 for (var i = 0; i < n; i++) { 47 if (i == 3) %OptimizeFunctionOnNextCall(use); 48 results[i] = use(objects[i], i); 49 } 50 51 // trigger migrations 52 if (verbose) { 53 print("-----------------------------"); 54 print("--- trigger migration"); 55 print(); 56 } 57 var migr = migr_desc.migr; 58 for (var i = 0; i < n; i++) { 59 if (i == 3) %OptimizeFunctionOnNextCall(migr); 60 migr(objects[i], i); 61 } 62 63 // use again 64 if (verbose) { 65 print("-----------------------------"); 66 print("--- use 2"); 67 print(); 68 } 69 var use = use_desc.use2 !== undefined ? use_desc.use2 : use_desc.use1; 70 for (var i = 0; i < n; i++) { 71 if (i == 3) %OptimizeFunctionOnNextCall(use); 72 results[i] = use(objects[i], i); 73 if (verbose >= 2) print(results[i]); 74 } 75 76 } catch (e) { 77 if (verbose) print("--- incompatible use: " + e); 78 } 79 return results; 80 } 81 82 83 var ctors = [ 84 { 85 name: "none-to-double", 86 ctor: function(v) { return {a: v}; }, 87 args: function(i) { return [1.5 + i]; }, 88 }, 89 { 90 name: "double", 91 ctor: function(v) { var o = {}; o.a = v; return o; }, 92 args: function(i) { return [1.5 + i]; }, 93 }, 94 { 95 name: "none-to-smi", 96 ctor: function(v) { return {a: v}; }, 97 args: function(i) { return [i]; }, 98 }, 99 { 100 name: "smi", 101 ctor: function(v) { var o = {}; o.a = v; return o; }, 102 args: function(i) { return [i]; }, 103 }, 104 { 105 name: "none-to-object", 106 ctor: function(v) { return {a: v}; }, 107 args: function(i) { return ["s"]; }, 108 }, 109 { 110 name: "object", 111 ctor: function(v) { var o = {}; o.a = v; return o; }, 112 args: function(i) { return ["s"]; }, 113 }, 114 { 115 name: "{a:, b:, c:}", 116 ctor: function(v1, v2, v3) { return {a: v1, b: v2, c: v3}; }, 117 args: function(i) { return [1.5 + i, 1.6, 1.7]; }, 118 }, 119 { 120 name: "{a..h:}", 121 ctor: function(v) { var o = {}; o.h=o.g=o.f=o.e=o.d=o.c=o.b=o.a=v; return o; }, 122 args: function(i) { return [1.5 + i]; }, 123 }, 124 { 125 name: "1", 126 ctor: function(v) { var o = 1; o.a = v; return o; }, 127 args: function(i) { return [1.5 + i]; }, 128 }, 129 { 130 name: "f()", 131 ctor: function(v) { var o = function() { return v;}; o.a = v; return o; }, 132 args: function(i) { return [1.5 + i]; }, 133 }, 134 { 135 name: "f().bind", 136 ctor: function(v) { var o = function(a,b,c) { return a+b+c; }; o = o.bind(o, v, v+1, v+2.2); return o; }, 137 args: function(i) { return [1.5 + i]; }, 138 }, 139 { 140 name: "dictionary elements", 141 ctor: function(v) { var o = []; o[1] = v; o[200000] = v; return o; }, 142 args: function(i) { return [1.5 + i]; }, 143 }, 144 { 145 name: "json", 146 ctor: function(v) { var json = '{"a":' + v + ',"b":' + v + '}'; return JSON.parse(json); }, 147 args: function(i) { return [1.5 + i]; }, 148 }, 149 { 150 name: "fast accessors", 151 accessor: { 152 get: function() { return this.a_; }, 153 set: function(value) {this.a_ = value; }, 154 configurable: true, 155 }, 156 ctor: function(v) { 157 var o = {a_:v}; 158 Object.defineProperty(o, "a", this.accessor); 159 return o; 160 }, 161 args: function(i) { return [1.5 + i]; }, 162 }, 163 { 164 name: "slow accessor", 165 accessor1: { value: this.a_, configurable: true }, 166 accessor2: { 167 get: function() { return this.a_; }, 168 set: function(value) {this.a_ = value; }, 169 configurable: true, 170 }, 171 ctor: function(v) { 172 var o = {a_:v}; 173 Object.defineProperty(o, "a", this.accessor1); 174 Object.defineProperty(o, "a", this.accessor2); 175 return o; 176 }, 177 args: function(i) { return [1.5 + i]; }, 178 }, 179 { 180 name: "slow", 181 proto: {}, 182 ctor: function(v) { 183 var o = {__proto__: this.proto}; 184 o.a = v; 185 for (var i = 0; %HasFastProperties(o); i++) o["f"+i] = v; 186 return o; 187 }, 188 args: function(i) { return [1.5 + i]; }, 189 }, 190 { 191 name: "global", 192 ctor: function(v) { return global; }, 193 args: function(i) { return [i]; }, 194 }, 195 ]; 196 197 198 199 var uses = [ 200 { 201 name: "o.a+1.0", 202 use1: function(o, i) { return o.a + 1.0; }, 203 use2: function(o, i) { return o.a + 1.1; }, 204 }, 205 { 206 name: "o.b+1.0", 207 use1: function(o, i) { return o.b + 1.0; }, 208 use2: function(o, i) { return o.b + 1.1; }, 209 }, 210 { 211 name: "o[1]+1.0", 212 use1: function(o, i) { return o[1] + 1.0; }, 213 use2: function(o, i) { return o[1] + 1.1; }, 214 }, 215 { 216 name: "o[-1]+1.0", 217 use1: function(o, i) { return o[-1] + 1.0; }, 218 use2: function(o, i) { return o[-1] + 1.1; }, 219 }, 220 { 221 name: "()", 222 use1: function(o, i) { return o() + 1.0; }, 223 use2: function(o, i) { return o() + 1.1; }, 224 }, 225 ]; 226 227 228 229 var migrations = [ 230 { 231 name: "to smi", 232 migr: function(o, i) { if (i == 0) o.a = 1; }, 233 }, 234 { 235 name: "to double", 236 migr: function(o, i) { if (i == 0) o.a = 1.1; }, 237 }, 238 { 239 name: "to object", 240 migr: function(o, i) { if (i == 0) o.a = {}; }, 241 }, 242 { 243 name: "set prototype {}", 244 migr: function(o, i) { o.__proto__ = {}; }, 245 }, 246 { 247 name: "%FunctionSetPrototype", 248 migr: function(o, i) { %FunctionSetPrototype(o, null); }, 249 }, 250 { 251 name: "modify prototype", 252 migr: function(o, i) { if (i == 0) o.__proto__.__proto1__ = [,,,5,,,]; }, 253 }, 254 { 255 name: "freeze prototype", 256 migr: function(o, i) { if (i == 0) Object.freeze(o.__proto__); }, 257 }, 258 { 259 name: "delete and re-add property", 260 migr: function(o, i) { var v = o.a; delete o.a; o.a = v; }, 261 }, 262 { 263 name: "modify prototype", 264 migr: function(o, i) { if (i >= 0) o.__proto__ = {}; }, 265 }, 266 { 267 name: "set property callback", 268 migr: function(o, i) { 269 Object.defineProperty(o, "a", { 270 get: function() { return 1.5 + i; }, 271 set: function(value) {}, 272 configurable: true, 273 }); 274 }, 275 }, 276 { 277 name: "seal", 278 migr: function(o, i) { Object.seal(o); }, 279 }, 280 { // Must be the last in the sequence, because after the global object freeze 281 // the other modifications does not make sence. 282 name: "freeze", 283 migr: function(o, i) { Object.freeze(o); }, 284 }, 285 ]; 286 287 288 289 migrations.forEach(function(migr) { 290 uses.forEach(function(use) { 291 ctors.forEach(function(ctor) { 292 test(ctor, use, migr); 293 }); 294 }); 295 }); 296