Commit 6345a240 authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[Turbofan] Brokerize scope info access in promise call reductions

This is a first step in eliminating heap access from a bevy of promise
reductions in js-call-reducer.cc. We begin by recognizing calls to
the affected builtins at serialization time, then serializing what
data is necessary.

Bug: v8:7790
Change-Id: Iaa1581eee730e8d3610a97c71eed635f77029455
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1657921
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62146}
parent 759bd180
......@@ -5599,6 +5599,12 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
if (!dependencies()->DependOnPromiseHookProtector()) return 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");
return NoChange();
}
SharedFunctionInfoRef promise_shared =
native_context().promise_function().shared();
......@@ -5641,7 +5647,7 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
// Allocate a promise context for the closures below.
Node* promise_context = effect = graph()->NewNode(
javascript()->CreateFunctionContext(
handle(native_context().object()->scope_info(), isolate()),
native_context().scope_info()->object(),
PromiseBuiltins::kPromiseContextLength - Context::MIN_CONTEXT_SLOTS,
FUNCTION_SCOPE),
context, effect, control);
......@@ -5887,6 +5893,12 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
}
}
// 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");
return inference.NoChange();
}
if (!dependencies()->DependOnPromiseHookProtector())
return inference.NoChange();
if (!dependencies()->DependOnPromiseThenProtector())
......@@ -5912,13 +5924,13 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
jsgraph()->Constant(native_context().promise_function());
// Allocate shared context for the closures below.
context = etrue = graph()->NewNode(
javascript()->CreateFunctionContext(
handle(native_context().object()->scope_info(), isolate()),
PromiseBuiltins::kPromiseFinallyContextLength -
Context::MIN_CONTEXT_SLOTS,
FUNCTION_SCOPE),
context, etrue, if_true);
context = etrue =
graph()->NewNode(javascript()->CreateFunctionContext(
native_context().scope_info()->object(),
PromiseBuiltins::kPromiseFinallyContextLength -
Context::MIN_CONTEXT_SLOTS,
FUNCTION_SCOPE),
context, etrue, if_true);
etrue = graph()->NewNode(
simplified()->StoreField(
AccessBuilder::ForContextSlot(PromiseBuiltins::kOnFinallySlot)),
......
......@@ -540,10 +540,14 @@ class ContextData : public HeapObjectData {
return search->second;
}
void SerializeScopeInfo(JSHeapBroker* broker);
ScopeInfoData* scope_info() const { return scope_info_; }
private:
ZoneMap<int, ObjectData*> slots_;
bool serialized_context_chain_ = false;
ContextData* previous_ = nullptr;
ScopeInfoData* scope_info_ = nullptr;
};
ContextData::ContextData(JSHeapBroker* broker, ObjectData** storage,
......@@ -574,6 +578,13 @@ void ContextData::SerializeSlot(JSHeapBroker* broker, int index) {
slots_.insert(std::make_pair(index, odata));
}
void ContextData::SerializeScopeInfo(JSHeapBroker* broker) {
TraceScope tracer(broker, this, "ContextData::SerializeScopeInfo");
TRACE(broker, "Serializing scope info");
Handle<Context> context = Handle<Context>::cast(object());
scope_info_ = broker->GetOrCreateData(context->scope_info())->AsScopeInfo();
}
class NativeContextData : public ContextData {
public:
#define DECL_ACCESSOR(type, name) \
......@@ -3351,6 +3362,26 @@ void ContextRef::SerializeSlot(int index) {
data()->AsContext()->SerializeSlot(broker(), index);
}
void ContextRef::SerializeScopeInfo() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsContext()->SerializeScopeInfo(broker());
}
base::Optional<ScopeInfoRef> ContextRef::scope_info() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference handle_dereference;
return ScopeInfoRef(broker(),
handle(object()->scope_info(), broker()->isolate()));
}
ScopeInfoData* scope_info = data()->AsContext()->scope_info();
if (scope_info != nullptr) {
return ScopeInfoRef(broker(), scope_info);
}
return base::Optional<ScopeInfoRef>();
}
void NativeContextRef::Serialize() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
......
......@@ -321,6 +321,11 @@ class ContextRef : public HeapObjectRef {
void SerializeSlot(int index);
ObjectRef get(int index) const;
// We only serialize the ScopeInfo if certain Promise
// builtins are called.
void SerializeScopeInfo();
base::Optional<ScopeInfoRef> scope_info() const;
};
#define BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \
......
......@@ -757,6 +757,9 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
if (shared->IsApiFunction()) {
ProcessApiCall(shared, arguments);
DCHECK(!shared->IsInlineable());
} else if (shared->HasBuiltinId()) {
ProcessBuiltinCall(shared);
DCHECK(!shared->IsInlineable());
}
if (!shared->IsInlineable() || !function->has_feedback_vector()) continue;
......@@ -771,6 +774,9 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
if (shared->IsApiFunction()) {
ProcessApiCall(shared, arguments);
DCHECK(!shared->IsInlineable());
} else if (shared->HasBuiltinId()) {
ProcessBuiltinCall(shared);
DCHECK(!shared->IsInlineable());
}
if (!shared->IsInlineable()) continue;
......@@ -853,6 +859,24 @@ void SerializerForBackgroundCompilation::ProcessReceiverMapForApiCall(
target.LookupHolderOfExpectedType(receiver_map, true);
}
void SerializerForBackgroundCompilation::ProcessBuiltinCall(
Handle<SharedFunctionInfo> target) {
DCHECK(target->HasBuiltinId());
int builtin_id = target->builtin_id();
switch (builtin_id) {
case Builtins::kPromiseConstructor:
TRACE_BROKER(broker(), "Found promise constructor");
broker()->native_context().SerializeScopeInfo();
break;
case Builtins::kPromisePrototypeFinally:
TRACE_BROKER(broker(), "Found promise prototype finally");
broker()->native_context().SerializeScopeInfo();
break;
default:
break;
}
}
void SerializerForBackgroundCompilation::ContributeToJumpTargetEnvironment(
int target_offset) {
auto it = jump_target_environments_.find(target_offset);
......
......@@ -324,6 +324,7 @@ class SerializerForBackgroundCompilation {
const HintsVector& arguments);
void ProcessReceiverMapForApiCall(FunctionTemplateInfoRef& target,
Handle<Map> receiver);
void ProcessBuiltinCall(Handle<SharedFunctionInfo> target);
void ProcessJump(interpreter::BytecodeArrayIterator* iterator);
......
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