Commit 8e30ac0f authored by Georg Neis's avatar Georg Neis Committed by V8 LUCI CQ

[compiler] Remove MapRef::serialized_prototype()

... in favour of an optional return type for MapRef::prototype().
This also eliminates one kind of use of ShouldHaveBeenSerialized(),
which I want to get rid of entirely.

Bug: v8:7790
Change-Id: I031f067d644570e5c8aaeaf94c5ff69ff0515a99
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2874456
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74385}
parent c933f2db
......@@ -680,7 +680,7 @@ namespace {
void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
base::Optional<JSObjectRef> last_prototype) {
while (true) {
HeapObjectRef proto = map.prototype();
HeapObjectRef proto = map.prototype().value();
if (!proto.IsJSObject()) {
CHECK_EQ(proto.map().oddball_type(), OddballType::kNull);
break;
......
......@@ -1162,9 +1162,8 @@ class MapData : public HeapObjectData {
void SerializePrototype(JSHeapBroker* broker) {
CHECK(TrySerializePrototype(broker));
}
bool serialized_prototype() const { return serialized_prototype_; }
ObjectData* prototype() const {
CHECK(serialized_prototype_);
DCHECK_EQ(serialized_prototype_, prototype_ != nullptr);
return prototype_;
}
......@@ -2935,7 +2934,7 @@ void MapData::SerializeForElementStore(JSHeapBroker* broker) {
MapRef map(broker, this);
do {
map.SerializePrototype();
map = map.prototype().map();
map = map.prototype().value().map();
} while (map.IsJSObjectMap() && map.is_stable() &&
IsFastElementsKind(map.elements_kind()));
}
......@@ -2943,14 +2942,14 @@ void MapData::SerializeForElementStore(JSHeapBroker* broker) {
bool MapRef::HasOnlyStablePrototypesWithFastElements(
ZoneVector<MapRef>* prototype_maps) {
DCHECK_NOT_NULL(prototype_maps);
MapRef prototype_map = prototype().map();
MapRef prototype_map = prototype().value().map();
while (prototype_map.oddball_type() != OddballType::kNull) {
if (!prototype_map.IsJSObjectMap() || !prototype_map.is_stable() ||
!IsFastElementsKind(prototype_map.elements_kind())) {
return false;
}
prototype_maps->push_back(prototype_map);
prototype_map = prototype_map.prototype().map();
prototype_map = prototype_map.prototype().value().map();
}
return true;
}
......@@ -3363,7 +3362,6 @@ BIMODAL_ACCESSOR_WITH_FLAG_B(Map, bit_field, is_undetectable,
BIMODAL_ACCESSOR_C(Map, int, instance_size)
BIMODAL_ACCESSOR_C(Map, int, NextFreePropertyIndex)
BIMODAL_ACCESSOR_C(Map, int, UnusedPropertyFields)
BIMODAL_ACCESSOR_WITH_FLAG(Map, HeapObject, prototype)
BIMODAL_ACCESSOR_WITH_FLAG_C(Map, InstanceType, instance_type)
BIMODAL_ACCESSOR_WITH_FLAG(Map, Object, GetConstructor)
BIMODAL_ACCESSOR_WITH_FLAG(Map, HeapObject, GetBackPointer)
......@@ -3454,23 +3452,16 @@ HolderLookupResult FunctionTemplateInfoRef::LookupHolderOfExpectedType(
if (policy == SerializationPolicy::kSerializeIfNeeded) {
receiver_map.SerializePrototype();
}
if (!receiver_map.serialized_prototype()) return not_found;
if (receiver_map.prototype().IsNull()) return not_found;
base::Optional<HeapObjectRef> prototype = receiver_map.prototype();
if (!prototype.has_value()) return not_found;
if (prototype->IsNull()) return not_found;
JSObject raw_prototype = JSObject::cast(*receiver_map.prototype().object());
JSObject raw_prototype = JSObject::cast(*prototype->object());
if (!expected_receiver_type.IsTemplateFor(raw_prototype.map())) {
return not_found;
}
Handle<JSObject> prototype =
broker()->CanonicalPersistentHandle(raw_prototype);
base::Optional<JSObjectRef> prototype_ref = TryMakeRef(broker(), prototype);
if (prototype_ref.has_value()) {
return HolderLookupResult(CallOptimization::kHolderFound, prototype_ref);
}
TRACE_BROKER_MISSING(broker(),
"holder for receiver with map " << receiver_map);
return not_found;
return HolderLookupResult(CallOptimization::kHolderFound,
prototype->AsJSObject());
}
FunctionTemplateInfoData* fti_data = data()->AsFunctionTemplateInfo();
......@@ -3585,6 +3576,16 @@ DescriptorArrayRef MapRef::instance_descriptors() const {
return DescriptorArrayRef(broker(), data()->AsMap()->instance_descriptors());
}
base::Optional<HeapObjectRef> MapRef::prototype() const {
IF_ACCESS_FROM_HEAP_WITH_FLAG(HeapObject, prototype);
ObjectData* prototype_data = data()->AsMap()->prototype();
if (prototype_data == nullptr) {
TRACE_BROKER_MISSING(broker(), "prototype for map " << *this);
return {};
}
return HeapObjectRef(broker(), prototype_data);
}
void MapRef::SerializeRootMap() {
if (data_->should_access_heap()) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
......@@ -4460,12 +4461,6 @@ bool MapRef::TrySerializePrototype() {
void MapRef::SerializePrototype() { CHECK(TrySerializePrototype()); }
bool MapRef::serialized_prototype() const {
if (data_->should_access_heap()) return true;
CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
return data()->AsMap()->serialized_prototype();
}
void SourceTextModuleRef::Serialize() {
if (data_->should_access_heap()) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
......
......@@ -689,10 +689,12 @@ class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
void SerializeBackPointer();
HeapObjectRef GetBackPointer() const;
bool TrySerializePrototype();
void SerializePrototype();
bool serialized_prototype() const;
HeapObjectRef prototype() const;
// TODO(neis): We should be able to remove TrySerializePrototype once
// concurrent-inlining is always on. Then we can also change the return type
// of prototype() back to HeapObjectRef.
bool TrySerializePrototype();
base::Optional<HeapObjectRef> prototype() const;
void SerializeForElementLoad();
......
......@@ -2595,25 +2595,17 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
MapRef first_receiver_map = MakeRef(broker(), receiver_maps[0]);
bool const is_constructor = first_receiver_map.is_constructor();
if (first_receiver_map.ShouldHaveBeenSerialized() &&
!first_receiver_map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(),
"serialized prototype on map " << first_receiver_map);
return inference.NoChange();
}
ObjectRef const prototype = first_receiver_map.prototype();
base::Optional<HeapObjectRef> const prototype =
first_receiver_map.prototype();
if (!prototype.has_value()) return inference.NoChange();
for (Handle<Map> const map : receiver_maps) {
MapRef receiver_map = MakeRef(broker(), map);
if (receiver_map.ShouldHaveBeenSerialized() &&
!receiver_map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(),
"serialized prototype on map " << receiver_map);
return inference.NoChange();
}
base::Optional<HeapObjectRef> map_prototype = receiver_map.prototype();
if (!map_prototype.has_value()) return inference.NoChange();
// Check for consistency among the {receiver_maps}.
if (!receiver_map.prototype().equals(prototype) ||
if (!map_prototype->equals(*prototype) ||
receiver_map.is_constructor() != is_constructor ||
!InstanceTypeChecker::IsJSFunctionOrBoundFunction(
receiver_map.instance_type())) {
......@@ -2669,7 +2661,7 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
MapRef map = is_constructor
? native_context().bound_function_with_constructor_map()
: native_context().bound_function_without_constructor_map();
if (!map.prototype().equals(prototype)) return inference.NoChange();
if (!map.prototype().value().equals(*prototype)) return inference.NoChange();
inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
control, p.feedback());
......@@ -2796,23 +2788,16 @@ Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
MapHandles const& object_maps = inference.GetMaps();
MapRef candidate_map = MakeRef(broker(), object_maps[0]);
if (candidate_map.ShouldHaveBeenSerialized() &&
!candidate_map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(), "prototype for map " << candidate_map);
return inference.NoChange();
}
ObjectRef candidate_prototype = candidate_map.prototype();
base::Optional<HeapObjectRef> candidate_prototype = candidate_map.prototype();
if (!candidate_prototype.has_value()) return inference.NoChange();
// Check if we can constant-fold the {candidate_prototype}.
for (size_t i = 0; i < object_maps.size(); ++i) {
MapRef object_map = MakeRef(broker(), object_maps[i]);
if (object_map.ShouldHaveBeenSerialized() &&
!object_map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(), "prototype for map " << object_map);
return inference.NoChange();
}
base::Optional<HeapObjectRef> map_prototype = object_map.prototype();
if (!map_prototype.has_value()) return inference.NoChange();
if (IsSpecialReceiverInstanceType(object_map.instance_type()) ||
!object_map.prototype().equals(candidate_prototype)) {
!map_prototype->equals(*candidate_prototype)) {
// We exclude special receivers, like JSProxy or API objects that
// might require access checks here; we also don't want to deal
// with hidden prototypes at this point.
......@@ -2825,7 +2810,7 @@ Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
if (!inference.RelyOnMapsViaStability(dependencies())) {
return inference.NoChange();
}
Node* value = jsgraph()->Constant(candidate_prototype);
Node* value = jsgraph()->Constant(*candidate_prototype);
ReplaceWithValue(node, value);
return Replace(value);
}
......@@ -6526,13 +6511,9 @@ bool JSCallReducer::DoPromiseChecks(MapInference* inference) {
for (Handle<Map> map : receiver_maps) {
MapRef receiver_map = MakeRef(broker(), map);
if (!receiver_map.IsJSPromiseMap()) return false;
if (receiver_map.ShouldHaveBeenSerialized() &&
!receiver_map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(), "prototype for map " << receiver_map);
return false;
}
if (!receiver_map.prototype().equals(
native_context().promise_prototype())) {
base::Optional<HeapObjectRef> prototype = receiver_map.prototype();
if (!prototype.has_value() ||
!prototype->equals(native_context().promise_prototype())) {
return false;
}
}
......
......@@ -1326,7 +1326,7 @@ base::Optional<MapRef> GetObjectCreateMap(JSHeapBroker* broker,
HeapObjectRef prototype) {
MapRef standard_map =
broker->target_native_context().object_function().initial_map();
if (prototype.equals(standard_map.prototype())) {
if (prototype.equals(standard_map.prototype().value())) {
return standard_map;
}
if (prototype.map().oddball_type() == OddballType::kNull) {
......
......@@ -364,19 +364,15 @@ Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
}
JSFunctionRef function = m.Ref(broker()).AsJSFunction();
MapRef function_map = function.map();
if (function_map.ShouldHaveBeenSerialized() &&
!function_map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(), "data for map " << function_map);
return NoChange();
}
HeapObjectRef function_prototype = function_map.prototype();
base::Optional<HeapObjectRef> function_prototype = function_map.prototype();
if (!function_prototype.has_value()) return NoChange();
// We can constant-fold the super constructor access if the
// {function}s map is stable, i.e. we can use a code dependency
// to guard against [[Prototype]] changes of {function}.
if (function_map.is_stable()) {
dependencies()->DependOnStableMap(function_map);
Node* value = jsgraph()->Constant(function_prototype);
Node* value = jsgraph()->Constant(*function_prototype);
ReplaceWithValue(node, value);
return Replace(value);
}
......@@ -552,15 +548,13 @@ JSNativeContextSpecialization::InferHasInPrototypeChain(
all = false;
break;
}
if (map.ShouldHaveBeenSerialized() && !map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(), "prototype data for map " << map);
return kMayBeInPrototypeChain;
}
if (map.prototype().equals(prototype)) {
base::Optional<HeapObjectRef> map_prototype = map.prototype();
if (!map_prototype.has_value()) return kMayBeInPrototypeChain;
if (map_prototype->equals(prototype)) {
none = false;
break;
}
map = map.prototype().map();
map = map_prototype->map();
// TODO(v8:11457) Support dictionary mode protoypes here.
if (!map.is_stable() || map.is_dictionary_map())
return kMayBeInPrototypeChain;
......@@ -3472,7 +3466,7 @@ bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
// native contexts, as the global Array protector works isolate-wide).
for (Handle<Map> map : receiver_maps) {
MapRef receiver_map = MakeRef(broker(), map);
ObjectRef receiver_prototype = receiver_map.prototype();
ObjectRef receiver_prototype = receiver_map.prototype().value();
if (!receiver_prototype.IsJSObject() ||
!broker()->IsArrayOrObjectPrototype(receiver_prototype.AsJSObject())) {
return false;
......
......@@ -1366,7 +1366,7 @@ void SerializerForBackgroundCompilation::VisitGetSuperConstructor(
MapRef map = MakeRef(broker(), handle(HeapObject::cast(*constant).map(),
broker()->isolate()));
map.SerializePrototype();
ObjectRef proto = map.prototype();
ObjectRef proto = map.prototype().value();
if (proto.IsHeapObject() && proto.AsHeapObject().map().is_constructor()) {
result_hints.AddConstant(proto.object(), zone(), broker());
}
......@@ -2613,7 +2613,7 @@ void SerializerForBackgroundCompilation::ProcessHintsForHasInPrototypeChain(
MapRef map = MakeRef(broker(), map_handle);
while (map.IsJSObjectMap()) {
map.SerializePrototype();
map = map.prototype().map();
map = map.prototype().value().map();
}
};
......
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