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);
%OptimizeFunctionOnNextCall(short_test);
short_a.length = 10;
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.
......
......@@ -205,7 +205,11 @@ assertEquals(0.5, array_store_1([], 0, 0.5));
grow_store(a,10,1);
assertOptimized(grow_store);
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);
})();
......@@ -254,6 +258,10 @@ assertEquals(0.5, array_store_1([], 0, 0.5));
assertOptimized(f);
// An attempt to grow should cause deopt
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);
})();
......@@ -63,6 +63,13 @@ assertUnoptimized(add_field, "no sync");
// Let concurrent recompilation proceed.
%UnblockConcurrentRecompilation();
// 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.
%ClearFunctionFeedback(add_field);
......@@ -125,8 +125,13 @@
let v1 = b.value;
maybe_sideeffect(b);
let v2 = b.value;
%TurbofanStaticAssert(Object.is(v1, v2));
%TurbofanStaticAssert(Object.is(v2, k));
if (!%IsDictPropertyConstTrackingEnabled()) {
// 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);
......@@ -151,8 +156,13 @@
let v1 = b.value;
maybe_sideeffect(b);
let v2 = b.value;
%TurbofanStaticAssert(Object.is(v1, v2));
%TurbofanStaticAssert(Object.is(v2, kk));
if (!%IsDictPropertyConstTrackingEnabled()) {
// 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);
......
......@@ -29,6 +29,13 @@
const b = makeObjectWithStableMap();
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.
assertUnoptimized(foo);
})();
......@@ -58,6 +65,13 @@
const b = makeObjectWithStableMap();
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.
assertUnoptimized(foo);
})();
......@@ -11,7 +11,12 @@ class C {
return 42;
}
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);
}
}
......
......@@ -5,7 +5,12 @@
// Flags: --allow-natives-syntax --opt --no-always-opt
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();
}
......
......@@ -5,7 +5,12 @@
// Flags: --allow-natives-syntax --opt --no-always-opt
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();
}
......
......@@ -9,7 +9,12 @@ var expect_interpreted = true;
function C() {
this.a = 1;
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() {
......
......@@ -104,7 +104,8 @@ function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) {
function warmup() { return new O().v; }
%EnsureFeedbackVectorForFunction(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
// map and therefore the compiler knows the prototype object and can
......
......@@ -101,7 +101,8 @@ function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) {
function warmup() { return new O().v; }
%EnsureFeedbackVectorForFunction(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
// map and therefore the compiler knows the prototype object and can
......
......@@ -32,7 +32,11 @@
foo(a, 3);
assertEquals(a[3], 5.3);
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));
%PrepareFunctionForOptimization(foo);
......
......@@ -48,7 +48,12 @@
// Assert that the function was deoptimized (dependency to the constant
// 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() {
......
......@@ -118,7 +118,12 @@
// Assert that the function was deoptimized (dependency to the constant
// 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() {
......@@ -239,7 +244,12 @@
assertEquals("new value", r);
// 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() {
......@@ -278,7 +288,13 @@
assertEquals("new value", r);
// 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() {
......
......@@ -163,7 +163,12 @@
%OptimizeFunctionOnNextCall(baz);
baz(f2, {b: 9});
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() {
......
......@@ -5,7 +5,15 @@
// Flags: --allow-natives-syntax
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));
assertEquals(!%IsDictPropertyConstTrackingEnabled(),
%HasFastProperties(Builtin.prototype.__proto__));
......
......@@ -10,6 +10,16 @@ function foo(first_run) {
Object.defineProperty(o, 'x', { get() { return 1; }, configurable: true, enumerable: true });
delete o.x;
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'));
}
%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