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