| // 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}); |