1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Flags: --allow-natives-syntax
6
7function PrintDesc(desc, s) {
8  var json;
9  if (desc) {
10    json = JSON.stringify(desc);
11  } else {
12    json = "<no such property>";
13  }
14  if (s === undefined) {
15    print(json);
16  } else {
17    print(s + ": " + json);
18  }
19}
20
21
22var counters;
23var test_realm;
24var cfg;
25
26
27function GetDescriptor() {
28  var code = 'Object.getOwnPropertyDescriptor(global, "x")';
29  var desc = Realm.eval(test_realm, code);
30//  PrintDesc(desc);
31  return desc;
32}
33
34function SetUp() {
35  counters = {};
36  Realm.shared = {counters: counters};
37  test_realm = Realm.create();
38  Realm.eval(test_realm, 'var global = Realm.global(Realm.current());');
39  print("=====================");
40  print("Test realm: " + test_realm);
41  assertEquals(undefined, GetDescriptor());
42}
43
44function TearDown() {
45  Realm.dispose(test_realm);
46  print("OK");
47}
48
49
50function AddStrict(code, cfg) {
51  return cfg.strict ? '"use strict"; ' + code : code;
52}
53
54function ForceMutablePropertyCellType() {
55  Realm.eval(test_realm, 'global.x = {}; global.x = undefined;');
56}
57
58function DeclareVar() {
59  var code = 'var x;';
60  return Realm.eval(test_realm, AddStrict(code, cfg));
61}
62
63function DefineVar(v) {
64  var code = 'var x = ' + v;
65  return Realm.eval(test_realm, AddStrict(code, cfg));
66}
67
68function DefineLoadVar() {
69  var name = 'LoadVar_' + test_realm;
70  var code =
71      'var x;' +
72      'function ' + name + '() {' +
73      '  return x;' +
74      '};';
75  return Realm.eval(test_realm, AddStrict(code, cfg));
76}
77
78function LoadVar() {
79  var name = 'LoadVar_' + test_realm;
80  var code =
81      (cfg.optimize ? '%OptimizeFunctionOnNextCall(' + name + ');' : '') +
82      name + '();';
83  return Realm.eval(test_realm, AddStrict(code, cfg));
84}
85
86function DefineStoreVar() {
87  var name = 'StoreVar_' + test_realm;
88  var code = 'var g = (Function("return this"))();' +
89      'var x;' +
90      'function ' + name + '(v) {' +
91//      '  %DebugPrint(g);' +
92      '  return x = v;' +
93      '};';
94  return Realm.eval(test_realm, AddStrict(code, cfg));
95}
96
97function StoreVar(v) {
98  var name = 'StoreVar_' + test_realm;
99  var code =
100      (cfg.optimize ? '%OptimizeFunctionOnNextCall(' + name + ');' : '') +
101      name + '(' + v + ');';
102  return Realm.eval(test_realm, AddStrict(code, cfg));
103}
104
105// It does 13 iterations which results in 27 loads
106// and 14 stores.
107function LoadStoreLoop() {
108  var code = 'for(var x = 0; x < 13; x++);';
109  return Realm.eval(test_realm, AddStrict(code, cfg));
110}
111
112function DefineRWDataProperty() {
113  var code =
114      'Object.defineProperty(global, "x", { ' +
115      '  value: 42, ' +
116      '  writable: true, ' +
117      '  enumerable: true, ' +
118      '  configurable: true ' +
119      '});';
120  return Realm.eval(test_realm, AddStrict(code, cfg));
121}
122
123function DefineRODataProperty() {
124  var code =
125      'Object.defineProperty(global, "x", { ' +
126      '  value: 42, ' +
127      '  writable: false, ' +
128      '  enumerable: true, ' +
129      '  configurable: true ' +
130      '});';
131  return Realm.eval(test_realm, AddStrict(code, cfg));
132}
133
134function SetX_(v) {
135  var code =
136      'global.x_ = ' + v + '; ';
137  return Realm.eval(test_realm, code);
138}
139
140function DefineRWAccessorProperty() {
141  var code =
142      'Object.defineProperty(global, "x", {' +
143      '  get: function() { Realm.shared.counters.get_count++; return this.x_; },' +
144      '  set: function(v) { Realm.shared.counters.set_count++; this.x_ = v; },' +
145      '  enumerable: true, configurable: true' +
146      '});';
147  counters.get_count = 0;
148  counters.set_count = 0;
149  return Realm.eval(test_realm, AddStrict(code, cfg));
150}
151
152function DefineROAccessorProperty() {
153  var code =
154      'Object.defineProperty(global, "x", {' +
155      '  get: function() { Realm.shared.counters.get_count++; return this.x_; },' +
156      '  enumerable: true, configurable: true' +
157      '});';
158  counters.get_count = 0;
159  counters.set_count = 0;
160  return Realm.eval(test_realm, AddStrict(code, cfg));
161}
162
163
164function testSuite(opt_cfg) {
165  //
166  // Non strict.
167  //
168
169  (function() {
170    SetUp();
171    cfg = {optimize: opt_cfg.optimize, strict: false};
172    DeclareVar();
173    DefineLoadVar();
174    DefineStoreVar();
175    assertEquals(undefined, LoadVar());
176    assertEquals(false, GetDescriptor().configurable);
177
178    // Force property cell type to kMutable.
179    DefineVar(undefined);
180    DefineVar(153);
181    assertEquals(false, GetDescriptor().configurable);
182
183    assertEquals(153, LoadVar());
184    assertEquals(113, StoreVar(113));
185    assertEquals(113, LoadVar());
186    LoadStoreLoop();
187    assertEquals(13, LoadVar());
188    TearDown();
189  })();
190
191
192  (function() {
193    SetUp();
194    cfg = {optimize: opt_cfg.optimize, strict: false};
195    ForceMutablePropertyCellType();
196    DefineLoadVar();
197    DefineStoreVar();
198    DefineRWDataProperty();
199    assertEquals(42, LoadVar());
200    assertEquals(true, GetDescriptor().configurable);
201
202    DefineVar(153);
203    assertEquals(true, GetDescriptor().configurable);
204
205    assertEquals(153, LoadVar());
206    assertEquals(113, StoreVar(113));
207    assertEquals(113, LoadVar());
208    LoadStoreLoop();
209    assertEquals(13, LoadVar());
210
211    // Now reconfigure to accessor.
212    DefineRWAccessorProperty();
213    assertEquals(undefined, GetDescriptor().value);
214    assertEquals(true, GetDescriptor().configurable);
215    assertEquals(0, counters.get_count);
216    assertEquals(0, counters.set_count);
217
218    assertEquals(undefined, LoadVar());
219    assertEquals(1, counters.get_count);
220    assertEquals(0, counters.set_count);
221
222    LoadStoreLoop();
223    assertEquals(28, counters.get_count);
224    assertEquals(14, counters.set_count);
225
226    assertEquals(13, LoadVar());
227    assertEquals(29, counters.get_count);
228    assertEquals(14, counters.set_count);
229
230    TearDown();
231  })();
232
233
234  (function() {
235    SetUp();
236    cfg = {optimize: opt_cfg.optimize, strict: false};
237    ForceMutablePropertyCellType();
238    DefineLoadVar();
239    DefineStoreVar();
240    DefineRODataProperty();
241    assertEquals(42, LoadVar());
242    assertEquals(true, GetDescriptor().configurable);
243
244    DefineVar(153);
245
246    assertEquals(42, LoadVar());
247    assertEquals(113, StoreVar(113));
248    assertEquals(42, LoadVar());
249    LoadStoreLoop();
250    assertEquals(42, LoadVar());
251
252    // Now reconfigure to accessor property.
253    DefineRWAccessorProperty();
254    assertEquals(undefined, GetDescriptor().value);
255    assertEquals(true, GetDescriptor().configurable);
256    assertEquals(0, counters.get_count);
257    assertEquals(0, counters.set_count);
258
259    assertEquals(undefined, LoadVar());
260    assertEquals(1, counters.get_count);
261    assertEquals(0, counters.set_count);
262
263    LoadStoreLoop();
264    assertEquals(28, counters.get_count);
265    assertEquals(14, counters.set_count);
266
267    assertEquals(13, LoadVar());
268    assertEquals(29, counters.get_count);
269    assertEquals(14, counters.set_count);
270
271    TearDown();
272  })();
273
274
275  (function() {
276    SetUp();
277    cfg = {optimize: opt_cfg.optimize, strict: false};
278    ForceMutablePropertyCellType();
279    DefineLoadVar();
280    DefineStoreVar();
281    DefineRWAccessorProperty();
282    assertEquals(0, counters.get_count);
283    assertEquals(0, counters.set_count);
284    assertEquals(true, GetDescriptor().configurable);
285
286    assertEquals(undefined, LoadVar());
287    assertEquals(1, counters.get_count);
288    assertEquals(0, counters.set_count);
289
290    DefineVar(153);
291    assertEquals(true, GetDescriptor().configurable);
292    assertEquals(1, counters.get_count);
293    assertEquals(1, counters.set_count);
294
295    assertEquals(153, LoadVar());
296    assertEquals(2, counters.get_count);
297    assertEquals(1, counters.set_count);
298
299    assertEquals(113, StoreVar(113));
300    assertEquals(2, counters.get_count);
301    assertEquals(2, counters.set_count);
302
303    assertEquals(113, LoadVar());
304    assertEquals(3, counters.get_count);
305    assertEquals(2, counters.set_count);
306
307    LoadStoreLoop();
308    assertEquals(30, counters.get_count);
309    assertEquals(16, counters.set_count);
310
311    assertEquals(13, LoadVar());
312    assertEquals(31, counters.get_count);
313    assertEquals(16, counters.set_count);
314
315    // Now reconfigure to data property.
316    DefineRWDataProperty();
317    assertEquals(42, GetDescriptor().value);
318    assertEquals(42, LoadVar());
319    assertEquals(113, StoreVar(113));
320    assertEquals(31, counters.get_count);
321    assertEquals(16, counters.set_count);
322
323    TearDown();
324  })();
325
326
327  (function() {
328    SetUp();
329    cfg = {optimize: opt_cfg.optimize, strict: false};
330    ForceMutablePropertyCellType();
331    DefineLoadVar();
332    DefineStoreVar();
333    DefineROAccessorProperty();
334    assertEquals(0, counters.get_count);
335    assertEquals(0, counters.set_count);
336    assertEquals(true, GetDescriptor().configurable);
337
338    assertEquals(undefined, LoadVar());
339    assertEquals(1, counters.get_count);
340    assertEquals(0, counters.set_count);
341
342    SetX_(42);
343    assertEquals(42, LoadVar());
344    assertEquals(2, counters.get_count);
345    assertEquals(0, counters.set_count);
346
347    DefineVar(153);
348    assertEquals(true, GetDescriptor().configurable);
349    assertEquals(2, counters.get_count);
350    assertEquals(0, counters.set_count);
351
352    assertEquals(42, LoadVar());
353    assertEquals(3, counters.get_count);
354    assertEquals(0, counters.set_count);
355
356    assertEquals(113, StoreVar(113));
357    assertEquals(3, counters.get_count);
358    assertEquals(0, counters.set_count);
359
360    assertEquals(42, LoadVar());
361    assertEquals(4, counters.get_count);
362    assertEquals(0, counters.set_count);
363
364    LoadStoreLoop();
365    assertEquals(5, counters.get_count);
366    assertEquals(0, counters.set_count);
367
368    assertEquals(42, LoadVar());
369    assertEquals(6, counters.get_count);
370    assertEquals(0, counters.set_count);
371
372    // Now reconfigure to data property.
373    DefineRWDataProperty();
374    assertEquals(42, GetDescriptor().value);
375    assertEquals(42, LoadVar());
376    assertEquals(113, StoreVar(113));
377    assertEquals(6, counters.get_count);
378    assertEquals(0, counters.set_count);
379
380    TearDown();
381  })();
382
383
384  //
385  // Strict.
386  //
387
388  (function() {
389    SetUp();
390    cfg = {optimize: opt_cfg.optimize, strict: true};
391    DeclareVar();
392    DefineLoadVar();
393    DefineStoreVar();
394    assertEquals(undefined, LoadVar());
395    assertEquals(false, GetDescriptor().configurable);
396
397    // Force property cell type to kMutable.
398    DefineVar(undefined);
399    DefineVar(153);
400    assertEquals(false, GetDescriptor().configurable);
401
402    assertEquals(153, LoadVar());
403    assertEquals(113, StoreVar(113));
404    assertEquals(113, LoadVar());
405    LoadStoreLoop();
406    assertEquals(13, LoadVar());
407    TearDown();
408  })();
409
410
411  (function() {
412    SetUp();
413    cfg = {optimize: opt_cfg.optimize, strict: true};
414    ForceMutablePropertyCellType();
415    DefineLoadVar();
416    DefineStoreVar();
417    DefineRWDataProperty();
418    assertEquals(42, LoadVar());
419    assertEquals(true, GetDescriptor().configurable);
420
421    DefineVar(153);
422    assertEquals(true, GetDescriptor().configurable);
423
424    assertEquals(153, LoadVar());
425    assertEquals(113, StoreVar(113));
426    assertEquals(113, LoadVar());
427    LoadStoreLoop();
428    assertEquals(13, LoadVar());
429    TearDown();
430  })();
431
432
433  (function() {
434    SetUp();
435    cfg = {optimize: opt_cfg.optimize, strict: true};
436    ForceMutablePropertyCellType();
437    DefineLoadVar();
438    DefineStoreVar();
439    DefineRWDataProperty();
440    assertEquals(true, GetDescriptor().configurable);
441    assertEquals(true, GetDescriptor().writable);
442    assertEquals(113, StoreVar(113));
443
444    DefineRODataProperty();
445    assertEquals(true, GetDescriptor().configurable);
446    assertEquals(false, GetDescriptor().writable);
447
448    assertEquals(42, LoadVar());
449    assertEquals(true, GetDescriptor().configurable);
450    assertThrows('DefineVar(153)');
451    assertEquals(42, LoadVar());
452    assertThrows('StoreVar(113)');
453    assertThrows('StoreVar(113)');
454    assertEquals(42, LoadVar());
455    assertThrows('StoreVar(42)');
456    assertEquals(42, LoadVar());
457    assertThrows('LoadStoreLoop()');
458    assertEquals(42, LoadVar());
459    TearDown();
460  })();
461
462
463  (function() {
464    SetUp();
465    cfg = {optimize: opt_cfg.optimize, strict: true};
466    ForceMutablePropertyCellType();
467    DefineLoadVar();
468    DefineStoreVar();
469    DefineRWAccessorProperty();
470    assertEquals(0, counters.get_count);
471    assertEquals(0, counters.set_count);
472    assertEquals(true, GetDescriptor().configurable);
473
474    assertEquals(undefined, LoadVar());
475    assertEquals(1, counters.get_count);
476    assertEquals(0, counters.set_count);
477
478    DefineVar(153);
479    assertEquals(true, GetDescriptor().configurable);
480    assertEquals(1, counters.get_count);
481    assertEquals(1, counters.set_count);
482
483    assertEquals(153, LoadVar());
484    assertEquals(2, counters.get_count);
485    assertEquals(1, counters.set_count);
486
487    assertEquals(113, StoreVar(113));
488    assertEquals(2, counters.get_count);
489    assertEquals(2, counters.set_count);
490
491    assertEquals(113, LoadVar());
492    assertEquals(3, counters.get_count);
493    assertEquals(2, counters.set_count);
494
495    LoadStoreLoop();
496    assertEquals(30, counters.get_count);
497    assertEquals(16, counters.set_count);
498
499    assertEquals(13, LoadVar());
500    assertEquals(31, counters.get_count);
501    assertEquals(16, counters.set_count);
502
503    // Now reconfigure to data property.
504    DefineRWDataProperty();
505    assertEquals(42, GetDescriptor().value);
506    assertEquals(42, LoadVar());
507    assertEquals(113, StoreVar(113));
508    assertEquals(31, counters.get_count);
509    assertEquals(16, counters.set_count);
510
511    TearDown();
512  })();
513
514
515  (function() {
516    SetUp();
517    cfg = {optimize: opt_cfg.optimize, strict: true};
518    ForceMutablePropertyCellType();
519    DefineLoadVar();
520    DefineStoreVar();
521    DefineROAccessorProperty();
522    assertEquals(0, counters.get_count);
523    assertEquals(0, counters.set_count);
524    assertEquals(true, GetDescriptor().configurable);
525
526    assertEquals(undefined, LoadVar());
527    assertEquals(1, counters.get_count);
528    assertEquals(0, counters.set_count);
529
530    SetX_(42);
531    assertEquals(42, LoadVar());
532    assertEquals(2, counters.get_count);
533    assertEquals(0, counters.set_count);
534
535    assertThrows('DefineVar(153)');
536    assertEquals(true, GetDescriptor().configurable);
537    assertEquals(2, counters.get_count);
538    assertEquals(0, counters.set_count);
539
540    assertEquals(42, LoadVar());
541    assertEquals(3, counters.get_count);
542    assertEquals(0, counters.set_count);
543
544    assertThrows('StoreVar(113)');
545    assertEquals(3, counters.get_count);
546    assertEquals(0, counters.set_count);
547
548    assertEquals(42, LoadVar());
549    assertEquals(4, counters.get_count);
550    assertEquals(0, counters.set_count);
551
552    assertThrows('LoadStoreLoop()');
553    assertEquals(4, counters.get_count);
554    assertEquals(0, counters.set_count);
555
556    assertEquals(42, LoadVar());
557    assertEquals(5, counters.get_count);
558    assertEquals(0, counters.set_count);
559
560    // Now reconfigure to data property.
561    DefineRWDataProperty();
562    assertEquals(42, GetDescriptor().value);
563    assertEquals(42, LoadVar());
564    assertEquals(113, StoreVar(113));
565    assertEquals(5, counters.get_count);
566    assertEquals(0, counters.set_count);
567
568    TearDown();
569  })();
570
571}  // testSuite
572
573
574testSuite({optimize: false});
575testSuite({optimize: true});
576