Commit e6fb0002 authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[Turbofan] brokerize native ctx spec. JSResolvePromise method

In native context specialization, reducing a JSResolvePromise
node requires us to know that there are no "then" properties on
the resolution object's maps. This work must be done at serialization
time.

Bug: v8:7790
Change-Id: If905513a028bc3d71379e2a31e86fff1d3383141
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1666988Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62519}
parent 425ab4ea
......@@ -2004,7 +2004,8 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone,
RefsMap(kMinimalRefsBucketCount, AddressMatcher(), zone())),
array_and_object_prototypes_(zone()),
tracing_enabled_(tracing_enabled),
feedback_(zone()) {
feedback_(zone()),
ais_for_loading_then_(zone()) {
// Note that this initialization of the refs_ pointer with the minimal
// initial capacity is redundant in the normal use case (concurrent
// compilation enabled, standard objects to be serialized), as the map
......@@ -3875,6 +3876,28 @@ base::Optional<NameRef> JSHeapBroker::GetNameFeedback(
return NameRef(this, handle(raw_name, isolate()));
}
PropertyAccessInfo JSHeapBroker::GetAccessInfoForLoadingThen(MapRef map) {
auto access_info = ais_for_loading_then_.find(map);
if (access_info == ais_for_loading_then_.end()) {
TRACE_BROKER_MISSING(
this, "access info for reducing JSResolvePromise with map " << map);
return PropertyAccessInfo::Invalid(zone());
}
return access_info->second;
}
void JSHeapBroker::CreateAccessInfoForLoadingThen(
MapRef map, CompilationDependencies* dependencies) {
auto access_info = ais_for_loading_then_.find(map);
if (access_info == ais_for_loading_then_.end()) {
AccessInfoFactory access_info_factory(this, dependencies, zone());
Handle<Name> then_string = isolate()->factory()->then_string();
ais_for_loading_then_.insert(
std::make_pair(map, access_info_factory.ComputePropertyAccessInfo(
map.object(), then_string, AccessMode::kLoad)));
}
}
ElementAccessFeedback const* ProcessedFeedback::AsElementAccess() const {
CHECK_EQ(kElementAccess, kind());
return static_cast<ElementAccessFeedback const*>(this);
......
......@@ -143,6 +143,17 @@ class V8_EXPORT_PRIVATE ObjectRef {
Isolate* isolate() const;
struct Hash {
size_t operator()(const ObjectRef& ref) const {
return base::hash_combine(ref.object().address());
}
};
struct Equal {
bool operator()(const ObjectRef& lhs, const ObjectRef& rhs) const {
return lhs.equals(rhs);
}
};
protected:
JSHeapBroker* broker() const;
ObjectData* data() const;
......@@ -953,6 +964,12 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
base::Optional<NameRef> GetNameFeedback(FeedbackNexus const& nexus);
// If there is no result stored for {map}, we return an Invalid
// PropertyAccessInfo.
PropertyAccessInfo GetAccessInfoForLoadingThen(MapRef map);
void CreateAccessInfoForLoadingThen(MapRef map,
CompilationDependencies* dependencies);
std::ostream& Trace();
void IncrementTracingIndentation();
void DecrementTracingIndentation();
......@@ -981,6 +998,10 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ZoneUnorderedMap<FeedbackSource, ProcessedFeedback const*,
FeedbackSource::Hash, FeedbackSource::Equal>
feedback_;
typedef ZoneUnorderedMap<MapRef, PropertyAccessInfo, ObjectRef::Hash,
ObjectRef::Equal>
MapToAccessInfos;
MapToAccessInfos ais_for_loading_then_;
static const size_t kMinimalRefsBucketCount = 8; // must be power of 2
static const size_t kInitialRefsBucketCount = 1024; // must be power of 2
......
......@@ -680,6 +680,7 @@ Reduction JSNativeContextSpecialization::ReduceJSPromiseResolve(Node* node) {
// ES section #sec-promise-resolve-functions
Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSResolvePromise, node->opcode());
Node* promise = NodeProperties::GetValueInput(node, 0);
Node* resolution = NodeProperties::GetValueInput(node, 1);
......@@ -696,9 +697,17 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
ZoneVector<PropertyAccessInfo> access_infos(graph()->zone());
AccessInfoFactory access_info_factory(broker(), dependencies(),
graph()->zone());
if (!FLAG_concurrent_inlining) {
access_info_factory.ComputePropertyAccessInfos(
resolution_maps, factory()->then_string(), AccessMode::kLoad,
&access_infos);
} else {
// Obtain pre-computed access infos from the broker.
for (auto map : resolution_maps) {
MapRef map_ref(broker(), map);
access_infos.push_back(broker()->GetAccessInfoForLoadingThen(map_ref));
}
}
PropertyAccessInfo access_info =
access_info_factory.FinalizePropertyAccessInfosAsOne(access_infos,
AccessMode::kLoad);
......
......@@ -324,7 +324,8 @@ std::ostream& operator<<(
if (i < env.parameter_count()) {
output_stream << "Hints for a" << i << ":\n";
} else if (i < env.parameter_count() + env.register_count()) {
output_stream << "Hints for r" << i << ":\n";
int local_register = i - env.parameter_count();
output_stream << "Hints for r" << local_register << ":\n";
} else if (i == env.accumulator_index()) {
output_stream << "Hints for <accumulator>:\n";
} else {
......@@ -586,6 +587,25 @@ void SerializerForBackgroundCompilation::VisitLdaSmi(
Smi::FromInt(iterator->GetImmediateOperand(0)), broker()->isolate()));
}
void SerializerForBackgroundCompilation::VisitInvokeIntrinsic(
BytecodeArrayIterator* iterator) {
Runtime::FunctionId functionId = iterator->GetIntrinsicIdOperand(0);
// For JSNativeContextSpecialization::ReduceJSAsyncFunctionResolve and
// JSNativeContextSpecialization::ReduceJSResolvePromise.
if (functionId == Runtime::kInlineAsyncFunctionResolve) {
interpreter::Register first_reg = iterator->GetRegisterOperand(1);
size_t reg_count = iterator->GetRegisterCountOperand(2);
CHECK_EQ(reg_count, 3);
HintsVector arguments(zone());
environment()->ExportRegisterHints(first_reg, reg_count, arguments);
Hints const& resolution_hints = arguments[1]; // The resolution object.
ProcessHintsForPromiseResolve(resolution_hints);
environment()->accumulator_hints().Clear();
return;
}
environment()->ClearEphemeralHints();
}
void SerializerForBackgroundCompilation::VisitLdaConstant(
BytecodeArrayIterator* iterator) {
environment()->accumulator_hints().Clear();
......@@ -1154,11 +1174,44 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
ProcessMapHintsForPromises(arguments[0]);
break;
}
case Builtins::kPromiseResolveTrampoline:
// For JSCallReducer::ReducePromiseInternalResolve and
// JSNativeContextSpecialization::ReduceJSResolvePromise.
if (arguments.size() >= 2) {
Hints const& resolution_hints = arguments[1];
ProcessHintsForPromiseResolve(resolution_hints);
}
break;
case Builtins::kPromiseInternalResolve:
// For JSCallReducer::ReducePromiseInternalResolve and
// JSNativeContextSpecialization::ReduceJSResolvePromise.
if (arguments.size() >= 3) {
Hints const& resolution_hints = arguments[2];
ProcessHintsForPromiseResolve(resolution_hints);
}
break;
default:
break;
}
}
void SerializerForBackgroundCompilation::ProcessHintsForPromiseResolve(
Hints const& resolution_hints) {
auto processMap = [&](Handle<Map> map) {
broker()->CreateAccessInfoForLoadingThen(MapRef(broker(), map),
dependencies());
};
for (auto hint : resolution_hints.constants()) {
if (!hint->IsJSReceiver()) continue;
Handle<JSReceiver> receiver(Handle<JSReceiver>::cast(hint));
processMap(handle(receiver->map(), broker()->isolate()));
}
for (auto map_hint : resolution_hints.maps()) {
processMap(map_hint);
}
}
void SerializerForBackgroundCompilation::ProcessMapHintsForPromises(
Hints const& receiver_hints) {
// We need to serialize the prototypes on each receiver map.
......@@ -1219,8 +1272,7 @@ void SerializerForBackgroundCompilation::VisitSwitchOnSmiNoFeedback(
void SerializerForBackgroundCompilation::Environment::ExportRegisterHints(
interpreter::Register first, size_t count, HintsVector& dst) {
dst.resize(dst.size() + count, Hints(zone()));
int reg_base = first.index();
const int reg_base = first.index();
for (int i = 0; i < static_cast<int>(count); ++i) {
dst.push_back(register_hints(interpreter::Register(reg_base + i)));
}
......
......@@ -174,6 +174,7 @@ namespace compiler {
V(CreateFunctionContext) \
V(CreateWithContext) \
V(GetSuperConstructor) \
V(InvokeIntrinsic) \
V(LdaConstant) \
V(LdaContextSlot) \
V(LdaCurrentContextSlot) \
......@@ -383,6 +384,7 @@ class SerializerForBackgroundCompilation {
void ProcessNamedPropertyAccess(Hints const& receiver, NameRef const& name,
FeedbackSlot slot, AccessMode mode);
void ProcessMapHintsForPromises(Hints const& receiver_hints);
void ProcessHintsForPromiseResolve(Hints const& resolution_hints);
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot);
NamedAccessFeedback const* ProcessFeedbackMapsForNamedAccess(
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/access-info.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-graph.h"
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/access-info.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/machine-operator.h"
......
......@@ -4,6 +4,7 @@
#include <vector>
#include "src/compiler/access-info.h"
#include "src/compiler/types.h"
#include "src/execution/isolate.h"
#include "src/heap/factory-inl.h"
......
......@@ -4,6 +4,7 @@
#include "src/compiler/common-operator-reducer.h"
#include "src/codegen/machine-type.h"
#include "src/compiler/access-info.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/operator.h"
......
......@@ -5,6 +5,7 @@
#include "src/compiler/constant-folding-reducer.h"
#include "src/codegen/code-factory.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
......
......@@ -4,6 +4,7 @@
#include "test/unittests/compiler/graph-unittest.h"
#include "src/compiler/access-info.h"
#include "src/compiler/js-heap-copy-reducer.h"
#include "src/compiler/node-properties.h"
#include "src/heap/factory.h"
......
......@@ -4,6 +4,7 @@
#include "src/compiler/simplified-operator-reducer.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
......
......@@ -5,6 +5,7 @@
#include <functional>
#include "src/base/overflowing-math.h"
#include "src/compiler/access-info.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
......
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