Commit 60fdd3ba authored by Mike Stanton's avatar Mike Stanton Committed by V8 LUCI CQ

[compiler] Improve GetOwnFastDataPropertyFromHeap representation check

Added a parameter to Object::FitsRepresentation() to disallow coercion.
Normally, when we ask if a Smi can "fit" into a Double representation
we'd answer yes, because the Smi can be converted to a HeapNumber.
However, from the compilers perspective, the object is found in a
field with a particular representation. In this case, finding a
Smi in a field with representation Double means something is awry.
Therefore, it's useful for the compiler to be able to ask if
the object fits the field without coercion.

Bug: chromium:1227324, v8:7790
Change-Id: I12033736030d904ef9c29516c07999600a5f508a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3015570
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75706}
parent ab686080
...@@ -514,16 +514,17 @@ base::Optional<ObjectRef> GetOwnFastDataPropertyFromHeap( ...@@ -514,16 +514,17 @@ base::Optional<ObjectRef> GetOwnFastDataPropertyFromHeap(
// {constant} needs to pass the gc predicate before we can introspect on it. // {constant} needs to pass the gc predicate before we can introspect on it.
if (broker->ObjectMayBeUninitialized(constant.value())) return {}; if (broker->ObjectMayBeUninitialized(constant.value())) return {};
// Since we don't have a guarantee that {constant} is the correct value of // Ensure that {constant} matches the {representation} we expect for the
// the property, we use the expected {representation} to weed out the most // field.
// egregious types of wrong values. if (!constant->FitsRepresentation(representation, false)) {
Representation constant_representation = const char* repString =
constant->OptimalRepresentation(broker->isolate()); constant->IsSmi()
if (!constant_representation.CanBeInPlaceChangedTo(representation)) { ? "Smi"
TRACE_BROKER_MISSING(broker, : constant->IsHeapNumber() ? "HeapNumber" : "HeapObject";
"Mismatched representation for " TRACE_BROKER_MISSING(broker, "Mismatched representation for "
<< holder << ". Expected " << representation << holder << ". Expected "
<< ", have: " << constant_representation); << representation << ", but object is a "
<< repString);
return {}; return {};
} }
} }
......
...@@ -497,11 +497,12 @@ ElementsKind Object::OptimalElementsKind(PtrComprCageBase cage_base) const { ...@@ -497,11 +497,12 @@ ElementsKind Object::OptimalElementsKind(PtrComprCageBase cage_base) const {
return PACKED_ELEMENTS; return PACKED_ELEMENTS;
} }
bool Object::FitsRepresentation(Representation representation) { bool Object::FitsRepresentation(Representation representation,
bool allow_coercion) const {
if (FLAG_track_fields && representation.IsSmi()) { if (FLAG_track_fields && representation.IsSmi()) {
return IsSmi(); return IsSmi();
} else if (FLAG_track_double_fields && representation.IsDouble()) { } else if (FLAG_track_double_fields && representation.IsDouble()) {
return IsNumber(); return allow_coercion ? IsNumber() : IsHeapNumber();
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
return IsHeapObject(); return IsHeapObject();
} else if (FLAG_track_fields && representation.IsNone()) { } else if (FLAG_track_fields && representation.IsNone()) {
......
...@@ -327,7 +327,11 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> { ...@@ -327,7 +327,11 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
inline ElementsKind OptimalElementsKind(PtrComprCageBase cage_base) const; inline ElementsKind OptimalElementsKind(PtrComprCageBase cage_base) const;
inline bool FitsRepresentation(Representation representation); // If {allow_coercion} is true, then a Smi will be considered to fit
// a Double representation, since it can be converted to a HeapNumber
// and stored.
inline bool FitsRepresentation(Representation representation,
bool allow_coercion = true) const;
inline bool FilterKey(PropertyFilter filter); inline bool FilterKey(PropertyFilter filter);
......
...@@ -3145,6 +3145,48 @@ TEST(DeletePropertyGeneralizesConstness) { ...@@ -3145,6 +3145,48 @@ TEST(DeletePropertyGeneralizesConstness) {
} }
} }
#define CHECK_SAME(object, rep, expected) \
CHECK_EQ(object->FitsRepresentation(rep, true), \
object->FitsRepresentation(rep, false)); \
CHECK_EQ(object->FitsRepresentation(rep, true), expected)
TEST(CheckFitsRepresentationPredicate) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
i::Factory* factory = CcTest::i_isolate()->factory();
Handle<Smi> smi_value = factory->last_script_id();
Handle<HeapNumber> double_value = factory->nan_value();
Handle<OrderedHashMap> heapobject_value = factory->empty_ordered_hash_map();
Representation rep_smi = Representation::Smi();
Representation rep_double = Representation::Double();
Representation rep_heapobject = Representation::HeapObject();
Representation rep_tagged = Representation::Tagged();
// Verify the behavior of Object::FitsRepresentation() with and
// without coercion. A Smi can be "coerced" into a Double
// representation by converting it to a HeapNumber. If coercion is
// disallowed, that query should fail.
CHECK_SAME(smi_value, rep_smi, true);
CHECK_EQ(smi_value->FitsRepresentation(rep_double, true), true);
CHECK_EQ(smi_value->FitsRepresentation(rep_double, false), false);
CHECK_SAME(smi_value, rep_heapobject, false);
CHECK_SAME(smi_value, rep_tagged, true);
CHECK_SAME(double_value, rep_smi, false);
CHECK_SAME(double_value, rep_double, true);
CHECK_SAME(double_value, rep_heapobject, true);
CHECK_SAME(double_value, rep_tagged, true);
CHECK_SAME(heapobject_value, rep_smi, false);
CHECK_SAME(heapobject_value, rep_double, false);
CHECK_SAME(heapobject_value, rep_heapobject, true);
CHECK_SAME(heapobject_value, rep_tagged, true);
}
#undef CHECK_SAME
} // namespace test_field_type_tracking } // namespace test_field_type_tracking
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
// Copyright 2021 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 --concurrent-inlining
(function() {
var use_symbol = {
[Symbol.hasInstance] : () => true
};
var use_symbol_double = {
[Symbol.hasInstance] : 0.1
};
function bar(b) {
if (b) return {} instanceof use_symbol_double;
}
%PrepareFunctionForOptimization(bar);
function foo(b) { return bar(); }
%PrepareFunctionForOptimization(foo);
foo();
%OptimizeFunctionOnNextCall(foo);
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