Commit c9b4f3c4 authored by Frank Emrich's avatar Frank Emrich Committed by Commit Bot

[dict-proto] TF support for constants in dictionary mode protos, pt. 4

This CL is part of a  series that implements Turbofan support for
property accesses satisfying the following conditions:
1. The holder is a dictionary mode object.
2. The holder is a prototype.
3. The access is a load.

This feature will only be enabled if the build flag
v8_dict_property_const_tracking is set.

This particular CL modifies existing mjsunit tests whose assumptions
don't hold if v8_dict_property_const_tracking is enabled. This is
done by adding special handling for the case that
%IsDictPropertyConstTrackingEnabled() holds.

Bug: v8:11248
Change-Id: Ia36be73e4659a988b2471f0c8151b0442f3a98f5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2780292
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73745}
parent d9cf7c20
...@@ -218,7 +218,11 @@ short_test(short_a, 50); ...@@ -218,7 +218,11 @@ short_test(short_a, 50);
%OptimizeFunctionOnNextCall(short_test); %OptimizeFunctionOnNextCall(short_test);
short_a.length = 10; short_a.length = 10;
short_test(short_a, 0); short_test(short_a, 0);
assertUnoptimized(short_test); // TODO(v8:11457) Currently, we cannot inline stores if there is a dictionary
// mode prototype on the prototype chain. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only contains
// a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(), isOptimized(short_test));
// A test for when we would modify a phi index. // A test for when we would modify a phi index.
......
...@@ -205,7 +205,11 @@ assertEquals(0.5, array_store_1([], 0, 0.5)); ...@@ -205,7 +205,11 @@ assertEquals(0.5, array_store_1([], 0, 0.5));
grow_store(a,10,1); grow_store(a,10,1);
assertOptimized(grow_store); assertOptimized(grow_store);
grow_store(a,2048,1); grow_store(a,2048,1);
assertUnoptimized(grow_store); // TODO(v8:11457) We don't currently support inlining element stores if there
// is a dictionary mode prototype on the prototype chain. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(), isOptimized(grow_store));
%ClearFunctionFeedback(grow_store); %ClearFunctionFeedback(grow_store);
})(); })();
...@@ -254,6 +258,10 @@ assertEquals(0.5, array_store_1([], 0, 0.5)); ...@@ -254,6 +258,10 @@ assertEquals(0.5, array_store_1([], 0, 0.5));
assertOptimized(f); assertOptimized(f);
// An attempt to grow should cause deopt // An attempt to grow should cause deopt
f(new Array("hi"), 1, 3); f(new Array("hi"), 1, 3);
assertUnoptimized(f); // TODO(v8:11457) We don't currently support inlining element stores if there
// is a dictionary mode prototype on the prototype chain. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(), isOptimized(f));
%ClearFunctionFeedback(f); %ClearFunctionFeedback(f);
})(); })();
...@@ -63,6 +63,13 @@ assertUnoptimized(add_field, "no sync"); ...@@ -63,6 +63,13 @@ assertUnoptimized(add_field, "no sync");
// Let concurrent recompilation proceed. // Let concurrent recompilation proceed.
%UnblockConcurrentRecompilation(); %UnblockConcurrentRecompilation();
// Sync with background thread to conclude optimization that bailed out. // Sync with background thread to conclude optimization that bailed out.
assertUnoptimized(add_field, "sync"); if (!%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11457) Currently, we cannot inline property stores if there is a
// dictionary mode prototype on the prototype chain. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get invalidated when the
// transition map changes.
assertUnoptimized(add_field, "sync");
}
// Clear type info for stress runs. // Clear type info for stress runs.
%ClearFunctionFeedback(add_field); %ClearFunctionFeedback(add_field);
...@@ -125,8 +125,13 @@ ...@@ -125,8 +125,13 @@
let v1 = b.value; let v1 = b.value;
maybe_sideeffect(b); maybe_sideeffect(b);
let v2 = b.value; let v2 = b.value;
%TurbofanStaticAssert(Object.is(v1, v2)); if (!%IsDictPropertyConstTrackingEnabled()) {
%TurbofanStaticAssert(Object.is(v2, k)); // TODO(v8:11457) If v8_dict_property_const_tracking is enabled, then
// b has a dictionary mode prototype and the load elimination doesn't
// work, yet.
%TurbofanStaticAssert(Object.is(v1, v2));
%TurbofanStaticAssert(Object.is(v2, k));
}
} }
%EnsureFeedbackVectorForFunction(B); %EnsureFeedbackVectorForFunction(B);
...@@ -151,8 +156,13 @@ ...@@ -151,8 +156,13 @@
let v1 = b.value; let v1 = b.value;
maybe_sideeffect(b); maybe_sideeffect(b);
let v2 = b.value; let v2 = b.value;
%TurbofanStaticAssert(Object.is(v1, v2)); if (!%IsDictPropertyConstTrackingEnabled()) {
%TurbofanStaticAssert(Object.is(v2, kk)); // TODO(v8:11457) If v8_dict_property_const_tracking is enabled, then
// b has a dictionary mode prototype and the load elimination doesn't
// work, yet.
%TurbofanStaticAssert(Object.is(v1, v2));
%TurbofanStaticAssert(Object.is(v2, kk));
}
} }
%EnsureFeedbackVectorForFunction(B); %EnsureFeedbackVectorForFunction(B);
......
...@@ -29,6 +29,13 @@ ...@@ -29,6 +29,13 @@
const b = makeObjectWithStableMap(); const b = makeObjectWithStableMap();
b.d = 1; b.d = 1;
if (%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11457) In this mode we weren't able to inline the access, yet, so
// it stays optimized. See related TODO in
// JSNativeContextSpecialization::ReduceJSResolvePromise.
return;
}
// This should deoptimize foo. // This should deoptimize foo.
assertUnoptimized(foo); assertUnoptimized(foo);
})(); })();
...@@ -58,6 +65,13 @@ ...@@ -58,6 +65,13 @@
const b = makeObjectWithStableMap(); const b = makeObjectWithStableMap();
b.z = 1; b.z = 1;
if (%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11457) In this mode we weren't able to inline the access, yet, so
// it stays optimized. See related TODO in
// JSNativeContextSpecialization::ReduceJSResolvePromise.
return;
}
// This should deoptimize foo. // This should deoptimize foo.
assertUnoptimized(foo); assertUnoptimized(foo);
})(); })();
...@@ -11,7 +11,12 @@ class C { ...@@ -11,7 +11,12 @@ class C {
return 42; return 42;
} }
set prop(v) { set prop(v) {
assertEquals(expect_interpreted, %IsBeingInterpreted()); if (!%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11457) If v8_dict_property_const_tracking is enabled, then
// C.prototype is a dictionary mode object and we cannot inline the call
// to this setter, yet.
assertEquals(expect_interpreted, %IsBeingInterpreted());
}
%TurbofanStaticAssert(v === 43); %TurbofanStaticAssert(v === 43);
} }
} }
......
...@@ -5,7 +5,12 @@ ...@@ -5,7 +5,12 @@
// Flags: --allow-natives-syntax --opt --no-always-opt // Flags: --allow-natives-syntax --opt --no-always-opt
function f(x) { function f(x) {
%TurbofanStaticAssert(x.foo === 42); // TODO(v8:11457) If v8_dict_property_const_tracking is enabled, then the
// prototype of |x| in |main| is a dictionary mode object, and we cannot
// inline the storing of x.foo, yet.
if (!%IsDictPropertyConstTrackingEnabled()) {
%TurbofanStaticAssert(x.foo === 42);
}
return %IsBeingInterpreted(); return %IsBeingInterpreted();
} }
......
...@@ -5,7 +5,12 @@ ...@@ -5,7 +5,12 @@
// Flags: --allow-natives-syntax --opt --no-always-opt // Flags: --allow-natives-syntax --opt --no-always-opt
function f(x) { function f(x) {
%TurbofanStaticAssert(x.foo === 42); if (!%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11457) If v8_dict_property_const_tracking is enabled, then the
// prototype of |x| in |main| is a dictionary mode object, and we cannot
// inline the storing of x.foo, yet.
%TurbofanStaticAssert(x.foo === 42);
}
return %IsBeingInterpreted(); return %IsBeingInterpreted();
} }
......
...@@ -9,7 +9,12 @@ var expect_interpreted = true; ...@@ -9,7 +9,12 @@ var expect_interpreted = true;
function C() { function C() {
this.a = 1; this.a = 1;
assertEquals(expect_interpreted, %IsBeingInterpreted()); assertEquals(expect_interpreted, %IsBeingInterpreted());
%TurbofanStaticAssert(this.x == 42); if (!%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11457) If v8_dict_property_const_tracking is enabled, then the
// prototype of |this| in D() is a dictionary mode object, and we cannot
// inline the storing of this.x, yet.
%TurbofanStaticAssert(this.x == 42);
}
}; };
function D() { function D() {
......
...@@ -104,7 +104,8 @@ function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) { ...@@ -104,7 +104,8 @@ function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) {
function warmup() { return new O().v; } function warmup() { return new O().v; }
%EnsureFeedbackVectorForFunction(warmup); %EnsureFeedbackVectorForFunction(warmup);
warmup(); warmup(); warmup(); warmup(); warmup(); warmup();
assertTrue(%HasFastProperties(O.prototype)); if (!%IsDictPropertyConstTrackingEnabled())
assertTrue(%HasFastProperties(O.prototype));
// The parameter object is not constant but all the values have the same // The parameter object is not constant but all the values have the same
// map and therefore the compiler knows the prototype object and can // map and therefore the compiler knows the prototype object and can
......
...@@ -101,7 +101,8 @@ function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) { ...@@ -101,7 +101,8 @@ function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) {
function warmup() { return new O().v; } function warmup() { return new O().v; }
%EnsureFeedbackVectorForFunction(warmup); %EnsureFeedbackVectorForFunction(warmup);
warmup(); warmup(); warmup(); warmup(); warmup(); warmup();
assertTrue(%HasFastProperties(O.prototype)); if (!%IsDictPropertyConstTrackingEnabled())
assertTrue(%HasFastProperties(O.prototype));
// The parameter object is not constant but all the values have the same // The parameter object is not constant but all the values have the same
// map and therefore the compiler knows the prototype object and can // map and therefore the compiler knows the prototype object and can
......
...@@ -32,7 +32,11 @@ ...@@ -32,7 +32,11 @@
foo(a, 3); foo(a, 3);
assertEquals(a[3], 5.3); assertEquals(a[3], 5.3);
foo(a, 50000); foo(a, 50000);
assertUnoptimized(foo); // TODO(v8:11457) We don't currently support inlining element stores if there
// is a dictionary mode prototypes on the prototype chain. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(), isOptimized(foo));
assertTrue(%HasDictionaryElements(a)); assertTrue(%HasDictionaryElements(a));
%PrepareFunctionForOptimization(foo); %PrepareFunctionForOptimization(foo);
......
...@@ -48,7 +48,12 @@ ...@@ -48,7 +48,12 @@
// Assert that the function was deoptimized (dependency to the constant // Assert that the function was deoptimized (dependency to the constant
// value). // value).
assertUnoptimized(C.prototype.foo); // TODO(v8:11457) We don't support inlining JSLoadNamedFromSuper for
// dictionary mode prototypes, yet. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(),
isOptimized(C.prototype.foo));
})(); })();
(function TestSuperpropertyAccessInlined() { (function TestSuperpropertyAccessInlined() {
......
...@@ -118,7 +118,12 @@ ...@@ -118,7 +118,12 @@
// Assert that the function was deoptimized (dependency to the constant // Assert that the function was deoptimized (dependency to the constant
// value). // value).
assertUnoptimized(D.prototype.foo); // TODO(v8:11457) We don't support inlining JSLoadNamedFromSuper for
// dictionary mode prototypes, yet. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(),
isOptimized(D.prototype.foo));
})(); })();
(function TestPropertyIsNonConstantData() { (function TestPropertyIsNonConstantData() {
...@@ -239,7 +244,12 @@ ...@@ -239,7 +244,12 @@
assertEquals("new value", r); assertEquals("new value", r);
// Assert that the function was deoptimized (holder changed). // Assert that the function was deoptimized (holder changed).
assertUnoptimized(C.prototype.foo); // TODO(v8:11457) We don't support inlining JSLoadNamedFromSuper for
// dictionary mode prototypes, yet. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(),
isOptimized(C.prototype.foo));
})(); })();
(function TestUnexpectedHomeObjectPrototypeDeoptimizes() { (function TestUnexpectedHomeObjectPrototypeDeoptimizes() {
...@@ -278,7 +288,13 @@ ...@@ -278,7 +288,13 @@
assertEquals("new value", r); assertEquals("new value", r);
// Assert that the function was deoptimized. // Assert that the function was deoptimized.
assertUnoptimized(D.prototype.foo); // TODO(v8:11457) We don't support inlining JSLoadNamedFromSuper for
// dictionary mode prototypes, yet. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(),
isOptimized(D.prototype.foo));
})(); })();
(function TestUnexpectedReceiverDoesNotDeoptimize() { (function TestUnexpectedReceiverDoesNotDeoptimize() {
......
...@@ -163,7 +163,12 @@ ...@@ -163,7 +163,12 @@
%OptimizeFunctionOnNextCall(baz); %OptimizeFunctionOnNextCall(baz);
baz(f2, {b: 9}); baz(f2, {b: 9});
baz(f3, {a: -1}); baz(f3, {a: -1});
assertUnoptimized(baz); // TODO(v8:11457) Currently, Turbofan/Turboprop can never inline any stores if
// there is a dictionary mode object in the protoype chain. Therefore, if
// v8_dict_property_const_tracking is enabled, the optimized code only
// contains a call to the IC handler and doesn't get deopted.
assertEquals(%IsDictPropertyConstTrackingEnabled(),
isOptimized(baz));
})(); })();
(function() { (function() {
......
...@@ -5,7 +5,15 @@ ...@@ -5,7 +5,15 @@
// Flags: --allow-natives-syntax // Flags: --allow-natives-syntax
function TestBuiltinSubclassing(Builtin) { function TestBuiltinSubclassing(Builtin) {
assertTrue(%HasFastProperties(Builtin)); if (!%IsDictPropertyConstTrackingEnabled()) {
// TODO(v8:11248) In the current implementation of
// v8_dict_property_const_tracking, prototypes are converted to dictionary
// mode in many places, but we don't guarantee that they are *created* as
// dictionary mode objects, yet. This will be fixed in the future. Until
// then, if v8_dict_property_const_tracking is enabled, we cannot always
// know for sure if a builtin has been converted already or not.
assertTrue(%HasFastProperties(Builtin));
}
assertTrue(%HasFastProperties(Builtin.prototype)); assertTrue(%HasFastProperties(Builtin.prototype));
assertEquals(!%IsDictPropertyConstTrackingEnabled(), assertEquals(!%IsDictPropertyConstTrackingEnabled(),
%HasFastProperties(Builtin.prototype.__proto__)); %HasFastProperties(Builtin.prototype.__proto__));
......
...@@ -10,6 +10,16 @@ function foo(first_run) { ...@@ -10,6 +10,16 @@ function foo(first_run) {
Object.defineProperty(o, 'x', { get() { return 1; }, configurable: true, enumerable: true }); Object.defineProperty(o, 'x', { get() { return 1; }, configurable: true, enumerable: true });
delete o.x; delete o.x;
o.x = 23; o.x = 23;
if (%IsDictPropertyConstTrackingEnabled()) {
// TODO(11248, ishell) Adding a property always sets it to constant if
// V8_DICT_PROPERTY_CONST_TRACKING is enabled, even if the property was
// deleted before and is re-added. See
// LookupIterator::PrepareTransitionToDataProperty, specically the usage of
// PropertyDetails::kConstIfDictConstnessTracking in there.
return;
}
if (first_run) assertFalse(%HasOwnConstDataProperty(o, 'x')); if (first_run) assertFalse(%HasOwnConstDataProperty(o, 'x'));
} }
%PrepareFunctionForOptimization(foo); %PrepareFunctionForOptimization(foo);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment