[Turbofan] Brokerize more promise reductions in JSCallReducer
The functions * JSCallReducer::ReducePromisePrototypeThen * JSCallReducer::ReducePromisePrototypeFinally * JSCallReducer::ReducePromisePrototypeCatch need the prototype for all receiver maps to be serialized in order to take effect. We can do this by processing our receiver hints when processing a builtin call in the serializer. Bug: v8:7790 Change-Id: I3d9144924cf6926cfcd93b60ac703cfba2d3d93a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1660623 Commit-Queue: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Cr-Commit-Position: refs/heads/master@{#62208}
This commit is contained in:
parent
45a751a187
commit
c5b9eda7ca
@ -5812,6 +5812,31 @@ Reduction JSCallReducer::ReducePromiseInternalResolve(Node* node) {
|
||||
return Replace(value);
|
||||
}
|
||||
|
||||
bool JSCallReducer::DoPromiseChecks(MapInference* inference) {
|
||||
if (!inference->HaveMaps()) return false;
|
||||
MapHandles const& receiver_maps = inference->GetMaps();
|
||||
|
||||
// Check whether all {receiver_maps} are JSPromise maps and
|
||||
// have the initial Promise.prototype as their [[Prototype]].
|
||||
for (Handle<Map> map : receiver_maps) {
|
||||
MapRef receiver_map(broker(), map);
|
||||
if (!receiver_map.IsJSPromiseMap()) return false;
|
||||
if (!FLAG_concurrent_inlining) {
|
||||
receiver_map.SerializePrototype();
|
||||
} else if (!receiver_map.serialized_prototype()) {
|
||||
TRACE_BROKER_MISSING(broker(),
|
||||
"Unserialized prototype for map " << receiver_map);
|
||||
return false;
|
||||
}
|
||||
if (!receiver_map.prototype().equals(
|
||||
native_context().promise_prototype())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ES section #sec-promise.prototype.catch
|
||||
Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
|
||||
@ -5825,20 +5850,7 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
MapInference inference(broker(), receiver, effect);
|
||||
if (!inference.HaveMaps()) return NoChange();
|
||||
MapHandles const& receiver_maps = inference.GetMaps();
|
||||
|
||||
// Check whether all {receiver_maps} are JSPromise maps and
|
||||
// have the initial Promise.prototype as their [[Prototype]].
|
||||
for (Handle<Map> map : receiver_maps) {
|
||||
MapRef receiver_map(broker(), map);
|
||||
if (!receiver_map.IsJSPromiseMap()) return inference.NoChange();
|
||||
receiver_map.SerializePrototype();
|
||||
if (!receiver_map.prototype().equals(
|
||||
native_context().promise_prototype())) {
|
||||
return inference.NoChange();
|
||||
}
|
||||
}
|
||||
if (!DoPromiseChecks(&inference)) return NoChange();
|
||||
|
||||
if (!dependencies()->DependOnPromiseThenProtector())
|
||||
return inference.NoChange();
|
||||
@ -5878,21 +5890,9 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
|
||||
}
|
||||
|
||||
MapInference inference(broker(), receiver, effect);
|
||||
if (!inference.HaveMaps()) return NoChange();
|
||||
if (!DoPromiseChecks(&inference)) return NoChange();
|
||||
MapHandles const& receiver_maps = inference.GetMaps();
|
||||
|
||||
// Check whether all {receiver_maps} are JSPromise maps and
|
||||
// have the initial Promise.prototype as their [[Prototype]].
|
||||
for (Handle<Map> map : receiver_maps) {
|
||||
MapRef receiver_map(broker(), map);
|
||||
if (!receiver_map.IsJSPromiseMap()) return inference.NoChange();
|
||||
receiver_map.SerializePrototype();
|
||||
if (!receiver_map.prototype().equals(
|
||||
native_context().promise_prototype())) {
|
||||
return inference.NoChange();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have the required scope_info.
|
||||
if (!native_context().scope_info().has_value()) {
|
||||
TRACE_BROKER_MISSING(broker(), "data for native context scope_info");
|
||||
@ -6023,28 +6023,8 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
||||
|
||||
DisallowHeapAccessIf no_heap_acess(FLAG_concurrent_inlining);
|
||||
|
||||
MapInference inference(broker(), receiver, effect);
|
||||
if (!inference.HaveMaps()) return NoChange();
|
||||
MapHandles const& receiver_maps = inference.GetMaps();
|
||||
|
||||
// Check whether all {receiver_maps} are JSPromise maps and
|
||||
// have the initial Promise.prototype as their [[Prototype]].
|
||||
for (Handle<Map> map : receiver_maps) {
|
||||
MapRef receiver_map(broker(), map);
|
||||
if (!receiver_map.IsJSPromiseMap()) return inference.NoChange();
|
||||
if (!FLAG_concurrent_inlining) {
|
||||
receiver_map.SerializePrototype();
|
||||
} else if (!receiver_map.serialized_prototype()) {
|
||||
TRACE_BROKER_MISSING(broker(),
|
||||
"Unserialized prototype for map " << receiver_map);
|
||||
return inference.NoChange();
|
||||
}
|
||||
if (!receiver_map.prototype().equals(
|
||||
native_context().promise_prototype())) {
|
||||
return inference.NoChange();
|
||||
}
|
||||
}
|
||||
if (!DoPromiseChecks(&inference)) return inference.NoChange();
|
||||
|
||||
if (!dependencies()->DependOnPromiseHookProtector())
|
||||
return inference.NoChange();
|
||||
|
@ -29,6 +29,7 @@ struct FieldAccess;
|
||||
class JSGraph;
|
||||
class JSHeapBroker;
|
||||
class JSOperatorBuilder;
|
||||
class MapInference;
|
||||
class NodeProperties;
|
||||
class SimplifiedOperatorBuilder;
|
||||
|
||||
@ -191,6 +192,9 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
|
||||
|
||||
Reduction ReduceNumberConstructor(Node* node);
|
||||
|
||||
// Helper to verify promise receiver maps are as expected.
|
||||
bool DoPromiseChecks(MapInference* inference);
|
||||
|
||||
// Returns the updated {to} node, and updates control and effect along the
|
||||
// way.
|
||||
Node* DoFilterPostCallbackWork(ElementsKind kind, Node** control,
|
||||
|
@ -866,20 +866,48 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||
switch (builtin_id) {
|
||||
case Builtins::kPromiseConstructor: {
|
||||
TRACE_BROKER(broker(), "Serializing data for builtin PromiseConstructor");
|
||||
// For JSCallReducer::ReducePromiseConstructor.
|
||||
broker()->native_context().SerializeScopeInfo();
|
||||
break;
|
||||
}
|
||||
case Builtins::kPromisePrototypeCatch: {
|
||||
TRACE_BROKER(broker(),
|
||||
"Serializing data for builtin PromisePrototypeCatch");
|
||||
// For JSCallReducer::ReducePromisePrototypeCatch.
|
||||
broker()->native_context().SerializeScopeInfo();
|
||||
|
||||
CHECK_GE(arguments.size(), 1);
|
||||
Hints const& receiver_hints = arguments[0];
|
||||
ProcessMapHintsForPromises(receiver_hints);
|
||||
break;
|
||||
}
|
||||
case Builtins::kPromisePrototypeFinally: {
|
||||
TRACE_BROKER(broker(),
|
||||
"Serializing data for builtin PromisePrototypeFinally");
|
||||
// For JSCallReducer::ReducePromisePrototypeFinally.
|
||||
broker()->native_context().SerializeScopeInfo();
|
||||
|
||||
CHECK_GE(arguments.size(), 1);
|
||||
Hints const& receiver_hints = arguments[0];
|
||||
ProcessMapHintsForPromises(receiver_hints);
|
||||
break;
|
||||
}
|
||||
case Builtins::kPromisePrototypeThen: {
|
||||
TRACE_BROKER(broker(),
|
||||
"Serializing data for builtin PromisePrototypeThen");
|
||||
// For JSCallReducer::ReducePromisePrototypeThen.
|
||||
CHECK_GE(arguments.size(), 1);
|
||||
Hints const& receiver_hints = arguments[0];
|
||||
ProcessMapHintsForPromises(receiver_hints);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SerializerForBackgroundCompilation::ProcessMapHintsForPromises(
|
||||
Hints const& receiver_hints) {
|
||||
// We need to serialize the prototypes on each receiver map.
|
||||
for (auto hint : receiver_hints.constants()) {
|
||||
if (!hint->IsJSPromise()) continue;
|
||||
@ -893,12 +921,6 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||
MapRef receiver_mapref(broker(), receiver_map);
|
||||
receiver_mapref.SerializePrototype();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SerializerForBackgroundCompilation::ContributeToJumpTargetEnvironment(
|
||||
|
@ -335,6 +335,7 @@ class SerializerForBackgroundCompilation {
|
||||
AccessMode mode);
|
||||
void ProcessNamedPropertyAccess(Hints const& receiver, NameRef const& name,
|
||||
FeedbackSlot slot, AccessMode mode);
|
||||
void ProcessMapHintsForPromises(Hints const& receiver_hints);
|
||||
|
||||
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot);
|
||||
NamedAccessFeedback const* ProcessFeedbackMapsForNamedAccess(
|
||||
|
Loading…
Reference in New Issue
Block a user