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
7var global = Function('return this')();
8var verbose = 0;
9
10function 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
83var 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
199var 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
229var 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
289migrations.forEach(function(migr) {
290  uses.forEach(function(use) {
291    ctors.forEach(function(ctor) {
292      test(ctor, use, migr);
293    });
294  });
295});
296