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