[runtime] Enable eager boilerplate creation again

This partially reverts commit 015edc60ff.

Reason for revert: Performance regression on richards

Bug: v8:6211
Change-Id: Ib69a1ed90b2015addcc54d7f299bdd654d964b54
Reviewed-on: https://chromium-review.googlesource.com/544992
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46174}
This commit is contained in:
Camillo Bruni 2017-06-23 14:31:47 +02:00 committed by Commit Bot
parent 2b99d09e62
commit c503b80595
6 changed files with 68 additions and 219 deletions

View File

@ -207,25 +207,6 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
return copy;
}
class DeprecationUpdateContext {
public:
explicit DeprecationUpdateContext(Isolate* isolate) { isolate_ = isolate; }
Isolate* isolate() { return isolate_; }
bool ShouldCreateMemento(Handle<JSObject> object) { return false; }
inline void ExitScope(Handle<AllocationSite> scope_site,
Handle<JSObject> object) {}
Handle<AllocationSite> EnterNewScope() { return Handle<AllocationSite>(); }
Handle<AllocationSite> current() {
UNREACHABLE();
return Handle<AllocationSite>();
}
static const bool kCopying = false;
private:
Isolate* isolate_;
};
// AllocationSiteCreationContext aids in the creation of AllocationSites to
// accompany object literals.
class AllocationSiteCreationContext : public AllocationSiteContext {
@ -277,15 +258,6 @@ class AllocationSiteCreationContext : public AllocationSiteContext {
static const bool kCopying = false;
};
MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
DeprecationUpdateContext* site_context) {
JSObjectWalkVisitor<DeprecationUpdateContext> v(site_context, kNoHints);
MaybeHandle<JSObject> result = v.StructureWalk(object);
Handle<JSObject> for_assert;
DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
return result;
}
MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
AllocationSiteCreationContext* site_context) {
JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, kNoHints);
@ -482,15 +454,8 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
} else {
// Instantiate a JSArray or JSObject literal from the given {description}.
boilerplate = Boilerplate::Create(isolate, vector, description, flags);
if (IsUninitializedLiteralSite(literal_site)) {
PreInitializeLiteralSite(vector, literals_slot);
if (copy_hints == kNoHints) {
DeprecationUpdateContext update_context(isolate);
RETURN_ON_EXCEPTION(isolate, DeepWalk(boilerplate, &update_context),
JSObject);
}
return boilerplate;
}
// TODO(cbruni): enable pre-initialized state for boilerplates after
// investigating regressions.
// Install AllocationSite objects.
AllocationSiteCreationContext creation_context(isolate);
site = creation_context.EnterNewScope();

View File

@ -165,12 +165,6 @@ function fastliteralcase_smiholey(index, value) {
obj = fastliteralcase_smiholey(5, 1);
assertKind(elements_kind.fast_smi_only, obj);
assertHoley(obj);
// We only start tracking tranistion with the second instantiation.
obj = fastliteralcase_smiholey(5, 1);
assertKind(elements_kind.fast_smi_only, obj);
assertHoley(obj);
obj = fastliteralcase_smiholey(0, 1);
assertKind(elements_kind.fast_smi_only, obj);
assertHoley(obj);
@ -268,70 +262,27 @@ assertKind(elements_kind.fast, obj);
// Case: array constructor calls with out of date feedback.
// The boilerplate should incorporate all feedback, but the input array
// should be minimally transitioned based on immediate need.
(function TestLiteralTransition() {
function literal() {
return [1, 2, 3];
(function() {
function foo(i) {
// We have two cases, one for literals one for constructed arrays.
var a = (i == 0)
? [1, 2, 3]
: new Array(1, 2, 3);
return a;
}
var a = literal(); // No boilerplate created yet.
var b = literal(); // Created boilerplate here.
var c = literal(); // Created copy from boilerplate.
// Boilerplate goes holey smi.
b[5] = 1;
assertKind(elements_kind.fast_smi_only, a);
assertKind(elements_kind.fast_smi_only, b);
assertKind(elements_kind.fast_smi_only, c);
assertHoley(literal());
// {a} has been created before tracking was active and thus doesn't affect
// the boilerplate.
a[0] = 3.5;
assertKind(elements_kind.fast_double, a);
assertNotHoley(a);
// Check that modifying {a} didn't change the boilerplate.
var d = literal();
assertKind(elements_kind.fast_smi_only, d);
assertHoley(d);
// Boilerplate goes from holey smi to holey double
c[0] = 3.5;
assertKind(elements_kind.fast_double, c);
assertNotHoley(c);
var e = literal();
assertKind(elements_kind.fast_double, e);
assertHoley(e);
})();
(function TestConstructedArrayTransition() {
// Allocation site tracking is on from the first instantiation for constructor
// calls.
function array() {
return new Array(1, 2, 3);
for (i = 0; i < 2; i++) {
a = foo(i);
b = foo(i);
b[5] = 1; // boilerplate goes holey
assertHoley(foo(i));
a[0] = 3.5; // boilerplate goes holey double
assertKind(elements_kind.fast_double, a);
assertNotHoley(a);
c = foo(i);
assertKind(elements_kind.fast_double, c);
assertHoley(c);
}
var a = array();
var b = array();
// Transition kind goes to smi holey.
b[5] = 1;
assertKind(elements_kind.fast_smi_only, a);
assertNotHoley(a);
assertHoley(b);
assertKind(elements_kind.fast_smi_only, b);
assertHoley(array());
// Confirm that modifying {b} did change the transition kind.
var d = array();
assertKind(elements_kind.fast_smi_only, d);
assertHoley(d);
// Sets the transition kind to double.
a[0] = 3.5;
assertKind(elements_kind.fast_double, a);
assertNotHoley(a);
// Confirm that we get the general kind holey + double.
var e = array();
assertKind(elements_kind.fast_double, e);
assertHoley(e);
})();
function newarraycase_onearg(len, value) {
@ -424,35 +375,15 @@ gc();
return literal;
}
var obj = get_nested_literal();
assertKind(elements_kind.fast, obj);
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast_smi_only, obj[2]);
obj[0][0] = 3.5;
obj[2][0] = "hello";
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast, obj[2]);
// We start tracking the allocation site from the second instantiation on.
obj = get_nested_literal();
assertKind(elements_kind.fast, obj);
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast_smi_only, obj[2]);
obj[0][0] = 3.5;
obj[2][0] = "hello";
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast, obj[2]);
obj = get_nested_literal();
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast, obj[2]);
// A more complex nested literal case.
function get_deep_nested_literal() {
var literal = [[1], [[2], "hello"], 3, [4]];
@ -460,15 +391,6 @@ gc();
}
obj = get_deep_nested_literal();
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1][0]);
obj[0][0] = 3.5;
obj[1][0][0] = "goodbye";
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast, obj[1][0]);
obj = get_deep_nested_literal();
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1][0]);
obj[0][0] = 3.5;
obj[1][0][0] = "goodbye";
@ -502,12 +424,6 @@ gc();
assertKind(elements_kind.fast_smi_only, obj.array);
obj.array[1] = 3.5;
assertKind(elements_kind.fast_double, obj.array);
obj = get_object_literal();
assertKind(elements_kind.fast_smi_only, obj.array);
obj.array[1] = 3.5;
assertKind(elements_kind.fast_double, obj.array);
obj = get_object_literal();
assertKind(elements_kind.fast_double, obj.array);
@ -524,13 +440,6 @@ gc();
assertKind(elements_kind.fast_smi_only, obj.array[1]);
obj.array[1][0] = 3.5;
assertKind(elements_kind.fast_double, obj.array[1]);
obj = get_nested_object_literal();
assertKind(elements_kind.fast, obj.array);
assertKind(elements_kind.fast_smi_only, obj.array[1]);
obj.array[1][0] = 3.5;
assertKind(elements_kind.fast_double, obj.array[1]);
obj = get_nested_object_literal();
assertKind(elements_kind.fast_double, obj.array[1]);
@ -547,26 +456,8 @@ gc();
obj = get_nested_literal();
assertKind(elements_kind.fast, obj);
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast_smi_only, obj[2]);
obj[0][0] = 3.5;
obj[2][0] = "hello";
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast, obj[2]);
obj = get_nested_literal();
assertKind(elements_kind.fast, obj);
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast_smi_only, obj[2]);
obj[0][0] = 3.5;
obj[2][0] = "hello";
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
assertKind(elements_kind.fast, obj[2]);
obj = get_nested_literal();
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1]);
@ -579,15 +470,6 @@ gc();
}
obj = get_deep_nested_literal();
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1][0]);
obj[0][0] = 3.5;
obj[1][0][0] = "goodbye";
assertKind(elements_kind.fast_double, obj[0]);
assertKind(elements_kind.fast, obj[1][0]);
obj = get_deep_nested_literal();
assertKind(elements_kind.fast_smi_only, obj[0]);
assertKind(elements_kind.fast_smi_only, obj[1][0]);
obj[0][0] = 3.5;
obj[1][0][0] = "goodbye";

View File

@ -69,7 +69,7 @@ get_literal(3);
// It's important to store a from before we crankshaft get_literal, because
// mementos won't be created from crankshafted code at all.
a = get_literal(3);
%OptimizeFunctionOnNextCall(get_literal);
%OptimizeFunctionOnNextCall(get_literal);
get_literal(3);
assertOptimized(get_literal);
assertTrue(%HasFastSmiElements(a));
@ -86,7 +86,7 @@ assertUnoptimized(get_literal);
// Optimize again
get_literal(3);
%OptimizeFunctionOnNextCall(get_literal);
%OptimizeFunctionOnNextCall(get_literal);
b = get_literal(3);
assertTrue(%HasFastDoubleElements(b));
assertOptimized(get_literal);
@ -99,20 +99,9 @@ assertOptimized(get_literal);
return [a, b, c];
}
var a = bar(1, 2, 3);
assertKind(elements_kind.fast_smi_only, a);
a = bar(1, 2, 3);
a[0] = 3.5;
a[1] = 'hi';
assertKind(elements_kind.fast, a);
// We only start tracking transition information with the second
// instantiation.
var b = bar(1, 2, 3);
assertKind(elements_kind.fast_smi_only, b);
b[0] = 3.5;
b[1] = 'hi';
b = bar(1, 2, 3);
assertKind(elements_kind.fast, b);
var c = bar(1, 2, 3);
assertKind(elements_kind.fast, c);
})();

View File

@ -113,15 +113,11 @@
assertEquals(3, l.y.z)
}
f();
f();
f();
f(); f(); f();
%OptimizeFunctionOnNextCall(f);
f();
f();
f(); f();
%OptimizeFunctionOnNextCall(f);
f();
f();
f(); f();
})();

View File

@ -57,7 +57,8 @@ function testBasicPrototype() {
assertEquals(Object.getPrototypeOf(obj), Object.prototype);
assertEquals(Object.getPrototypeOf(obj.b), Object.prototype);
};
runTest(testBasicPrototype);
testBasicPrototype();
testBasicPrototype();
function testDynamicValue() {
var z = 24;
@ -73,9 +74,10 @@ function testDynamicValue() {
assertEquals(24, obj2.b.y);
assertEquals('Zebra', obj2.c);
}
runTest(testDynamicValue);
testDynamicValue();
testDynamicValue();
function testMultipleInstatiations() {
(function testMultipleInstatiations() {
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = {
@ -88,8 +90,7 @@ function testMultipleInstatiations() {
arr[0].b.x = 2;
assertEquals(2, arr[0].b.x);
assertEquals(12, arr[1].b.x);
}
runTest(testMultipleInstatiations);
})();
function testSparseElements() {
let sa1 = {
@ -253,7 +254,8 @@ function TestSimpleElements() {
o[0] = 0;
assertEquals({0:0, 1:"one", 2:"two"}, o);
}
runTest(TestSimpleElements);
TestSimpleElements();
TestSimpleElements();
function TestNumericNames() {
var o = {
@ -277,7 +279,8 @@ function TestNumericNames() {
%HeapObjectVerify(o);
assertEquals(['1.2', '1.3'], Object.keys(o));
}
runTest(TestNumericNames);
TestNumericNames();
TestNumericNames();
function TestDictionaryElements() {
let o = {1024: true};
@ -298,7 +301,10 @@ function TestDictionaryElements() {
o2[1024] = "test";
assertEquals(["test"], Object.values(o2));
}
runTest(TestDictionaryElements);
TestDictionaryElements();
TestDictionaryElements();
%OptimizeFunctionOnNextCall(TestDictionaryElements);
TestDictionaryElements();
function TestLiteralElementsKind() {
let o = {0:0, 1:1, 2:2};
@ -324,7 +330,10 @@ function TestLiteralElementsKind() {
assertTrue(%HasDictionaryElements({0xFFFFFF:true}));
}
runTest(TestLiteralElementsKind);
TestLiteralElementsKind();
TestLiteralElementsKind();
%OptimizeFunctionOnNextCall(TestLiteralElementsKind);
TestLiteralElementsKind();
function TestNonNumberElementValues() {
var o = {
@ -379,7 +388,11 @@ function TestNonNumberElementValues() {
%HeapObjectVerify(o4);
assertEquals(['1', '2', '3', '4', 'a', 'b'], Object.keys(o4));
}
runTest(TestNonNumberElementValues);
TestNonNumberElementValues();
TestNonNumberElementValues();
TestNonNumberElementValues();
%OptimizeFunctionOnNextCall(TestNonNumberElementValues);
TestNonNumberElementValues();
function numericGetters() {
@ -406,7 +419,8 @@ function numericGetters() {
get 1.30() {}
});
}
runTest(numericGetters);
numericGetters();
numericGetters();
function numericSetters() {
function TestNumericNamesSetter(expectedKeys, object) {
@ -432,7 +446,9 @@ function numericSetters() {
set 1.30(_) {; }
});
};
runTest(numericSetters);
numericSetters();
numericSetters();
function TestProxyWithDefinitionInObjectLiteral() {
// Trap for set should not be used if the definition
@ -448,12 +464,14 @@ function TestProxyWithDefinitionInObjectLiteral() {
p[prop] = 'my value';
assertEquals(undefined, p[prop]);
var l = new Proxy({[prop]: 'my value'}, handler);
assertEquals('my value', l[prop]);
};
runTest(TestProxyWithDefinitionInObjectLiteral);
TestProxyWithDefinitionInObjectLiteral();
TestProxyWithDefinitionInObjectLiteral();
function TestLiteralWithNullProto() {
(function TestLiteralWithNullProto() {
// Assume dictionary usage for simple null prototype literal objects,
// this is equivalent to Object.create(null). Note that on the first call
// the literal boilerplate is initialized, and from then on we use a the
@ -480,8 +498,7 @@ function TestLiteralWithNullProto() {
testDictModeNullProtoLiteral(() => ({a:1, b:2, __proto__:null}));
testDictModeNullProtoLiteral(() => ({["a"]: 1, __proto__: null}));
testDictModeNullProtoLiteral(() => ({a: Object, __proto__: null}));
}
runTest(TestLiteralWithNullProto);
})();
function testNestedNullProtoLiteral() {
let obj;
@ -507,7 +524,8 @@ function testNestedNullProtoLiteral() {
obj.foo.bar = "barValue2";
assertEquals("barValue2", obj.foo.bar);
}
runTest(testNestedNullProtoLiteral);
testNestedNullProtoLiteral();
testNestedNullProtoLiteral();
function TestSlowLiteralOptimized() {
@ -531,9 +549,10 @@ function TestSlowLiteralOptimized() {
obj.bar = "barValue2";
assertEquals("barValue2", obj.bar);
};
runTest(TestSlowLiteralOptimized);
TestSlowLiteralOptimized();
TestSlowLiteralOptimized();
function TestLargeDictionaryLiteral() {
(function TestLargeDictionaryLiteral() {
// Create potential large-space object literal.
function createObject() {
// This literal has least kMaxRegularHeapObjectSize / 64 number of
@ -1549,8 +1568,7 @@ function TestLargeDictionaryLiteral() {
assertFalse(%HasFastProperties(object2));
assertEquals(Object.getPrototypeOf(object2), null);
assertEquals(keys, Object.keys(object2));
}
runTest(TestLargeDictionaryLiteral);
})();
(function TestPrototypeInObjectLiteral() {

View File

@ -29,12 +29,11 @@ function literals_sharing_test(warmup, optimize) {
function test() {
var warmup = true;
for (var i = 0; i < 3; i++) {
// We only start tracking allocation information with the second
// instantiation.
var warmup = i < 2;
print("iter: " + i + ", warmup: "+ warmup);
literals_sharing_test(warmup, false);
warmup = false;
}
print("iter: " + i + ", opt: true");
literals_sharing_test(warmup, true);