| // Copyright 2015 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // Flags: --allow-natives-syntax | 
 |  | 
 | function PrintDesc(desc, s) { | 
 |   var json; | 
 |   if (desc) { | 
 |     json = JSON.stringify(desc); | 
 |   } else { | 
 |     json = "<no such property>"; | 
 |   } | 
 |   if (s === undefined) { | 
 |     print(json); | 
 |   } else { | 
 |     print(s + ": " + json); | 
 |   } | 
 | } | 
 |  | 
 |  | 
 | var counters; | 
 | var test_realm; | 
 | var cfg; | 
 |  | 
 |  | 
 | function GetDescriptor() { | 
 |   var code = 'Object.getOwnPropertyDescriptor(global, "x")'; | 
 |   var desc = Realm.eval(test_realm, code); | 
 | //  PrintDesc(desc); | 
 |   return desc; | 
 | } | 
 |  | 
 | function SetUp() { | 
 |   counters = {}; | 
 |   Realm.shared = {counters: counters}; | 
 |   test_realm = Realm.create(); | 
 |   Realm.eval(test_realm, 'var global = Realm.global(Realm.current());'); | 
 |   print("====================="); | 
 |   print("Test realm: " + test_realm); | 
 |   assertEquals(undefined, GetDescriptor()); | 
 | } | 
 |  | 
 | function TearDown() { | 
 |   Realm.dispose(test_realm); | 
 |   print("OK"); | 
 | } | 
 |  | 
 |  | 
 | function AddStrict(code, cfg) { | 
 |   return cfg.strict ? '"use strict"; ' + code : code; | 
 | } | 
 |  | 
 | function ForceMutablePropertyCellType() { | 
 |   Realm.eval(test_realm, 'global.x = {}; global.x = undefined;'); | 
 | } | 
 |  | 
 | function DeclareVar() { | 
 |   var code = 'var x;'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function DefineVar(v) { | 
 |   var code = 'var x = ' + v; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function DefineLoadVar() { | 
 |   var name = 'LoadVar_' + test_realm; | 
 |   var code = | 
 |       'var x;' + | 
 |       'function ' + name + '() {' + | 
 |       '  return x;' + | 
 |       '};'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function LoadVar() { | 
 |   var name = 'LoadVar_' + test_realm; | 
 |   var code = | 
 |       (cfg.optimize ? '%OptimizeFunctionOnNextCall(' + name + ');' : '') + | 
 |       name + '();'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function DefineStoreVar() { | 
 |   var name = 'StoreVar_' + test_realm; | 
 |   var code = 'var g = (Function("return this"))();' + | 
 |       'var x;' + | 
 |       'function ' + name + '(v) {' + | 
 | //      '  %DebugPrint(g);' + | 
 |       '  return x = v;' + | 
 |       '};'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function StoreVar(v) { | 
 |   var name = 'StoreVar_' + test_realm; | 
 |   var code = | 
 |       (cfg.optimize ? '%OptimizeFunctionOnNextCall(' + name + ');' : '') + | 
 |       name + '(' + v + ');'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | // It does 13 iterations which results in 27 loads | 
 | // and 14 stores. | 
 | function LoadStoreLoop() { | 
 |   var code = 'for(var x = 0; x < 13; x++);'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function DefineRWDataProperty() { | 
 |   var code = | 
 |       'Object.defineProperty(global, "x", { ' + | 
 |       '  value: 42, ' + | 
 |       '  writable: true, ' + | 
 |       '  enumerable: true, ' + | 
 |       '  configurable: true ' + | 
 |       '});'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function DefineRODataProperty() { | 
 |   var code = | 
 |       'Object.defineProperty(global, "x", { ' + | 
 |       '  value: 42, ' + | 
 |       '  writable: false, ' + | 
 |       '  enumerable: true, ' + | 
 |       '  configurable: true ' + | 
 |       '});'; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function SetX_(v) { | 
 |   var code = | 
 |       'global.x_ = ' + v + '; '; | 
 |   return Realm.eval(test_realm, code); | 
 | } | 
 |  | 
 | function DefineRWAccessorProperty() { | 
 |   var code = | 
 |       'Object.defineProperty(global, "x", {' + | 
 |       '  get: function() { Realm.shared.counters.get_count++; return this.x_; },' + | 
 |       '  set: function(v) { Realm.shared.counters.set_count++; this.x_ = v; },' + | 
 |       '  enumerable: true, configurable: true' + | 
 |       '});'; | 
 |   counters.get_count = 0; | 
 |   counters.set_count = 0; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 | function DefineROAccessorProperty() { | 
 |   var code = | 
 |       'Object.defineProperty(global, "x", {' + | 
 |       '  get: function() { Realm.shared.counters.get_count++; return this.x_; },' + | 
 |       '  enumerable: true, configurable: true' + | 
 |       '});'; | 
 |   counters.get_count = 0; | 
 |   counters.set_count = 0; | 
 |   return Realm.eval(test_realm, AddStrict(code, cfg)); | 
 | } | 
 |  | 
 |  | 
 | function testSuite(opt_cfg) { | 
 |   // | 
 |   // Non strict. | 
 |   // | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: false}; | 
 |     DeclareVar(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(false, GetDescriptor().configurable); | 
 |  | 
 |     // Force property cell type to kMutable. | 
 |     DefineVar(undefined); | 
 |     DefineVar(153); | 
 |     assertEquals(false, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(153, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(113, LoadVar()); | 
 |     LoadStoreLoop(); | 
 |     assertEquals(13, LoadVar()); | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: false}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineRWDataProperty(); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     DefineVar(153); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(153, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(113, LoadVar()); | 
 |     LoadStoreLoop(); | 
 |     assertEquals(13, LoadVar()); | 
 |  | 
 |     // Now reconfigure to accessor. | 
 |     DefineRWAccessorProperty(); | 
 |     assertEquals(undefined, GetDescriptor().value); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(0, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     LoadStoreLoop(); | 
 |     assertEquals(28, counters.get_count); | 
 |     assertEquals(14, counters.set_count); | 
 |  | 
 |     assertEquals(13, LoadVar()); | 
 |     assertEquals(29, counters.get_count); | 
 |     assertEquals(14, counters.set_count); | 
 |  | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: false}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineRODataProperty(); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     DefineVar(153); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(42, LoadVar()); | 
 |     LoadStoreLoop(); | 
 |     assertEquals(42, LoadVar()); | 
 |  | 
 |     // Now reconfigure to accessor property. | 
 |     DefineRWAccessorProperty(); | 
 |     assertEquals(undefined, GetDescriptor().value); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(0, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     LoadStoreLoop(); | 
 |     assertEquals(28, counters.get_count); | 
 |     assertEquals(14, counters.set_count); | 
 |  | 
 |     assertEquals(13, LoadVar()); | 
 |     assertEquals(29, counters.get_count); | 
 |     assertEquals(14, counters.set_count); | 
 |  | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: false}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineRWAccessorProperty(); | 
 |     assertEquals(0, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     DefineVar(153); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(1, counters.set_count); | 
 |  | 
 |     assertEquals(153, LoadVar()); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(1, counters.set_count); | 
 |  | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(2, counters.set_count); | 
 |  | 
 |     assertEquals(113, LoadVar()); | 
 |     assertEquals(3, counters.get_count); | 
 |     assertEquals(2, counters.set_count); | 
 |  | 
 |     LoadStoreLoop(); | 
 |     assertEquals(30, counters.get_count); | 
 |     assertEquals(16, counters.set_count); | 
 |  | 
 |     assertEquals(13, LoadVar()); | 
 |     assertEquals(31, counters.get_count); | 
 |     assertEquals(16, counters.set_count); | 
 |  | 
 |     // Now reconfigure to data property. | 
 |     DefineRWDataProperty(); | 
 |     assertEquals(42, GetDescriptor().value); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(31, counters.get_count); | 
 |     assertEquals(16, counters.set_count); | 
 |  | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: false}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineROAccessorProperty(); | 
 |     assertEquals(0, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     SetX_(42); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     DefineVar(153); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(3, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(3, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(4, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     LoadStoreLoop(); | 
 |     assertEquals(5, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(6, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     // Now reconfigure to data property. | 
 |     DefineRWDataProperty(); | 
 |     assertEquals(42, GetDescriptor().value); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(6, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   // | 
 |   // Strict. | 
 |   // | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: true}; | 
 |     DeclareVar(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(false, GetDescriptor().configurable); | 
 |  | 
 |     // Force property cell type to kMutable. | 
 |     DefineVar(undefined); | 
 |     DefineVar(153); | 
 |     assertEquals(false, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(153, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(113, LoadVar()); | 
 |     LoadStoreLoop(); | 
 |     assertEquals(13, LoadVar()); | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: true}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineRWDataProperty(); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     DefineVar(153); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(153, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(113, LoadVar()); | 
 |     LoadStoreLoop(); | 
 |     assertEquals(13, LoadVar()); | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: true}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineRWDataProperty(); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(true, GetDescriptor().writable); | 
 |     assertEquals(113, StoreVar(113)); | 
 |  | 
 |     DefineRODataProperty(); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(false, GetDescriptor().writable); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertThrows('DefineVar(153)'); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertThrows('StoreVar(113)'); | 
 |     assertThrows('StoreVar(113)'); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertThrows('StoreVar(42)'); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertThrows('LoadStoreLoop()'); | 
 |     assertEquals(42, LoadVar()); | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: true}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineRWAccessorProperty(); | 
 |     assertEquals(0, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     DefineVar(153); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(1, counters.set_count); | 
 |  | 
 |     assertEquals(153, LoadVar()); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(1, counters.set_count); | 
 |  | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(2, counters.set_count); | 
 |  | 
 |     assertEquals(113, LoadVar()); | 
 |     assertEquals(3, counters.get_count); | 
 |     assertEquals(2, counters.set_count); | 
 |  | 
 |     LoadStoreLoop(); | 
 |     assertEquals(30, counters.get_count); | 
 |     assertEquals(16, counters.set_count); | 
 |  | 
 |     assertEquals(13, LoadVar()); | 
 |     assertEquals(31, counters.get_count); | 
 |     assertEquals(16, counters.set_count); | 
 |  | 
 |     // Now reconfigure to data property. | 
 |     DefineRWDataProperty(); | 
 |     assertEquals(42, GetDescriptor().value); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(31, counters.get_count); | 
 |     assertEquals(16, counters.set_count); | 
 |  | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 |  | 
 |   (function() { | 
 |     SetUp(); | 
 |     cfg = {optimize: opt_cfg.optimize, strict: true}; | 
 |     ForceMutablePropertyCellType(); | 
 |     DefineLoadVar(); | 
 |     DefineStoreVar(); | 
 |     DefineROAccessorProperty(); | 
 |     assertEquals(0, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |  | 
 |     assertEquals(undefined, LoadVar()); | 
 |     assertEquals(1, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     SetX_(42); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertThrows('DefineVar(153)'); | 
 |     assertEquals(true, GetDescriptor().configurable); | 
 |     assertEquals(2, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(3, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertThrows('StoreVar(113)'); | 
 |     assertEquals(3, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(4, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertThrows('LoadStoreLoop()'); | 
 |     assertEquals(4, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(5, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     // Now reconfigure to data property. | 
 |     DefineRWDataProperty(); | 
 |     assertEquals(42, GetDescriptor().value); | 
 |     assertEquals(42, LoadVar()); | 
 |     assertEquals(113, StoreVar(113)); | 
 |     assertEquals(5, counters.get_count); | 
 |     assertEquals(0, counters.set_count); | 
 |  | 
 |     TearDown(); | 
 |   })(); | 
 |  | 
 | }  // testSuite | 
 |  | 
 |  | 
 | testSuite({optimize: false}); | 
 | testSuite({optimize: true}); |