blob: fd235f997bf0264b079b946d2d07790960cb6aa2 [file] [log] [blame]
// 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});