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

[Turbofan] ContextRef::SerializeContextChain should take a depth param

We can save memory by only serializing a context chain to a
*required* depth if we know it.

Bug: v8:7790
Change-Id: I97d21f8cd7b56b26fddd95e00a26d5e520d96170
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1678358Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62795}
parent c2ee4a79
...@@ -326,15 +326,14 @@ class ContextRef : public HeapObjectRef { ...@@ -326,15 +326,14 @@ class ContextRef : public HeapObjectRef {
using HeapObjectRef::HeapObjectRef; using HeapObjectRef::HeapObjectRef;
Handle<Context> object() const; Handle<Context> object() const;
void SerializeContextChain(); // {previous} decrements {depth} by 1 for each previous link successfully
// followed. If {depth} != 0 on function return, then it only got
// {previous} decrements n by 1 for each previous link successfully // partway to the desired depth. If {serialize} is true, then
// followed. If depth != 0 on function return, then it only got // {previous} will cache its findings.
// partway to the desired depth. ContextRef previous(size_t* depth, bool serialize = false) const;
ContextRef previous(size_t* depth) const;
// Only returns a value if the index is valid for this ContextRef.
void SerializeSlot(int index); base::Optional<ObjectRef> get(int index, bool serialize = false) const;
base::Optional<ObjectRef> get(int index) const;
// We only serialize the ScopeInfo if certain Promise // We only serialize the ScopeInfo if certain Promise
// builtins are called. // builtins are called.
......
...@@ -576,21 +576,15 @@ class ContextData : public HeapObjectData { ...@@ -576,21 +576,15 @@ class ContextData : public HeapObjectData {
public: public:
ContextData(JSHeapBroker* broker, ObjectData** storage, ContextData(JSHeapBroker* broker, ObjectData** storage,
Handle<Context> object); Handle<Context> object);
void SerializeContextChain(JSHeapBroker* broker);
ContextData* previous() const { // {previous} will return the closest valid context possible to desired
return previous_; // {depth}, decrementing {depth} for each previous link successfully followed.
} // If {serialize} is true, it will serialize contexts along the way.
ContextData* previous(JSHeapBroker* broker, size_t* depth, bool serialize);
void SerializeSlot(JSHeapBroker* broker, int index);
ObjectData* GetSlot(int index) { // Returns nullptr if the slot index isn't valid or wasn't serialized
auto search = slots_.find(index); // (unless {serialize} is true).
if (search != slots_.end()) { ObjectData* GetSlot(JSHeapBroker* broker, int index, bool serialize);
return search->second;
}
return nullptr;
}
private: private:
ZoneMap<int, ObjectData*> slots_; ZoneMap<int, ObjectData*> slots_;
...@@ -601,25 +595,46 @@ ContextData::ContextData(JSHeapBroker* broker, ObjectData** storage, ...@@ -601,25 +595,46 @@ ContextData::ContextData(JSHeapBroker* broker, ObjectData** storage,
Handle<Context> object) Handle<Context> object)
: HeapObjectData(broker, storage, object), slots_(broker->zone()) {} : HeapObjectData(broker, storage, object), slots_(broker->zone()) {}
void ContextData::SerializeContextChain(JSHeapBroker* broker) { ContextData* ContextData::previous(JSHeapBroker* broker, size_t* depth,
if (previous_ != nullptr) return; bool serialize) {
if (*depth == 0) return this;
if (serialize && previous_ == nullptr) {
TraceScope tracer(broker, this, "ContextData::previous");
Handle<Context> context = Handle<Context>::cast(object());
Context prev = context->previous();
if (!prev.is_null()) {
previous_ = broker->GetOrCreateData(prev)->AsContext();
}
}
Handle<Context> context = Handle<Context>::cast(object()); if (previous_ != nullptr) {
// Context::previous DCHECK-fails when called on the native context. *depth = *depth - 1;
if (!context->IsNativeContext()) { return previous_->previous(broker, depth, serialize);
TraceScope tracer(broker, this, "ContextData::SerializeContextChain");
previous_ = broker->GetOrCreateData(context->previous())->AsContext();
previous_->SerializeContextChain(broker);
} }
return this;
} }
void ContextData::SerializeSlot(JSHeapBroker* broker, int index) { ObjectData* ContextData::GetSlot(JSHeapBroker* broker, int index,
TraceScope tracer(broker, this, "ContextData::SerializeSlot"); bool serialize) {
TRACE(broker, "Serializing context slot " << index); CHECK_GE(index, 0);
Handle<Context> context = Handle<Context>::cast(object()); auto search = slots_.find(index);
CHECK(index >= 0 && index < context->length()); if (search != slots_.end()) {
ObjectData* odata = broker->GetOrCreateData(context->get(index)); return search->second;
slots_.insert(std::make_pair(index, odata)); }
if (serialize) {
Handle<Context> context = Handle<Context>::cast(object());
if (index < context->length()) {
TraceScope tracer(broker, this, "ContextData::GetSlot");
TRACE(broker, "Serializing context slot " << index);
ObjectData* odata = broker->GetOrCreateData(context->get(index));
slots_.insert(std::make_pair(index, odata));
return odata;
}
}
return nullptr;
} }
class NativeContextData : public ContextData { class NativeContextData : public ContextData {
...@@ -2067,35 +2082,31 @@ bool ObjectRef::equals(const ObjectRef& other) const { ...@@ -2067,35 +2082,31 @@ bool ObjectRef::equals(const ObjectRef& other) const {
Isolate* ObjectRef::isolate() const { return broker()->isolate(); } Isolate* ObjectRef::isolate() const { return broker()->isolate(); }
ContextRef ContextRef::previous(size_t* depth) const { ContextRef ContextRef::previous(size_t* depth, bool serialize) const {
DCHECK_NOT_NULL(depth); DCHECK_NOT_NULL(depth);
DCHECK_GE(*depth, 0);
if (broker()->mode() == JSHeapBroker::kDisabled) { if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation; AllowHandleAllocation handle_allocation;
AllowHandleDereference handle_dereference; AllowHandleDereference handle_dereference;
Context current = *object(); Context current = *object();
while (*depth != 0) { while (*depth != 0 && !current.previous().is_null()) {
current = current.previous(); current = current.previous();
(*depth)--; (*depth)--;
} }
return ContextRef(broker(), handle(current, broker()->isolate())); return ContextRef(broker(), handle(current, broker()->isolate()));
} }
ContextData* current = this->data()->AsContext(); ContextData* current = this->data()->AsContext();
while (*depth != 0 && current->previous() != nullptr) { return ContextRef(broker(), current->previous(broker(), depth, serialize));
current = current->previous();
(*depth)--;
}
return ContextRef(broker(), current);
} }
base::Optional<ObjectRef> ContextRef::get(int index) const { base::Optional<ObjectRef> ContextRef::get(int index, bool serialize) const {
if (broker()->mode() == JSHeapBroker::kDisabled) { if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation; AllowHandleAllocation handle_allocation;
AllowHandleDereference handle_dereference; AllowHandleDereference handle_dereference;
Handle<Object> value(object()->get(index), broker()->isolate()); Handle<Object> value(object()->get(index), broker()->isolate());
return ObjectRef(broker(), value); return ObjectRef(broker(), value);
} }
ObjectData* optional_slot = data()->AsContext()->GetSlot(index); ObjectData* optional_slot =
data()->AsContext()->GetSlot(broker(), index, serialize);
if (optional_slot != nullptr) { if (optional_slot != nullptr) {
return ObjectRef(broker(), optional_slot); return ObjectRef(broker(), optional_slot);
} }
...@@ -3718,18 +3729,6 @@ void SourceTextModuleRef::Serialize() { ...@@ -3718,18 +3729,6 @@ void SourceTextModuleRef::Serialize() {
data()->AsSourceTextModule()->Serialize(broker()); data()->AsSourceTextModule()->Serialize(broker());
} }
void ContextRef::SerializeContextChain() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsContext()->SerializeContextChain(broker());
}
void ContextRef::SerializeSlot(int index) {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsContext()->SerializeSlot(broker(), index);
}
void NativeContextRef::Serialize() { void NativeContextRef::Serialize() {
if (broker()->mode() == JSHeapBroker::kDisabled) return; if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing); CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
...@@ -4053,7 +4052,7 @@ GlobalAccessFeedback const* JSHeapBroker::ProcessFeedbackForGlobalAccess( ...@@ -4053,7 +4052,7 @@ GlobalAccessFeedback const* JSHeapBroker::ProcessFeedbackForGlobalAccess(
} }
ContextRef context_ref(this, context); ContextRef context_ref(this, context);
if (immutable) { if (immutable) {
context_ref.SerializeSlot(context_slot_index); context_ref.get(context_slot_index, true);
} }
return new (zone()) return new (zone())
GlobalAccessFeedback(context_ref, context_slot_index, immutable); GlobalAccessFeedback(context_ref, context_slot_index, immutable);
......
...@@ -31,7 +31,6 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) { ...@@ -31,7 +31,6 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) {
if (object.IsJSFunction()) object.AsJSFunction().Serialize(); if (object.IsJSFunction()) object.AsJSFunction().Serialize();
if (object.IsJSObject()) object.AsJSObject().SerializeObjectCreateMap(); if (object.IsJSObject()) object.AsJSObject().SerializeObjectCreateMap();
if (object.IsSourceTextModule()) object.AsSourceTextModule().Serialize(); if (object.IsSourceTextModule()) object.AsSourceTextModule().Serialize();
if (object.IsContext()) object.AsContext().SerializeContextChain();
break; break;
} }
case IrOpcode::kJSCreateArray: { case IrOpcode::kJSCreateArray: {
......
...@@ -1106,13 +1106,11 @@ void SerializerForBackgroundCompilation::VisitPopContext( ...@@ -1106,13 +1106,11 @@ void SerializerForBackgroundCompilation::VisitPopContext(
void SerializerForBackgroundCompilation::ProcessImmutableLoad( void SerializerForBackgroundCompilation::ProcessImmutableLoad(
ContextRef& context_ref, int slot, ContextProcessingMode mode) { ContextRef& context_ref, int slot, ContextProcessingMode mode) {
DCHECK(mode == kSerializeSlot || mode == kSerializeSlotAndAddToAccumulator); DCHECK(mode == kSerializeSlot || mode == kSerializeSlotAndAddToAccumulator);
context_ref.SerializeSlot(slot); base::Optional<ObjectRef> slot_value = context_ref.get(slot, true);
// Also, put the object into the constant hints for the accumulator. // Also, put the object into the constant hints for the accumulator.
if (mode == kSerializeSlotAndAddToAccumulator) { if (mode == kSerializeSlotAndAddToAccumulator && slot_value.has_value()) {
Handle<Object> slot_value(context_ref.object()->get(slot), environment()->accumulator_hints().AddConstant(slot_value.value().object());
broker()->isolate());
environment()->accumulator_hints().AddConstant(slot_value);
} }
} }
...@@ -1128,28 +1126,20 @@ void SerializerForBackgroundCompilation::ProcessContextAccess( ...@@ -1128,28 +1126,20 @@ void SerializerForBackgroundCompilation::ProcessContextAccess(
if (x->IsContext()) { if (x->IsContext()) {
// Walk this context to the given depth and serialize the slot found. // Walk this context to the given depth and serialize the slot found.
ContextRef context_ref(broker(), x); ContextRef context_ref(broker(), x);
// TODO(mvstanton): Add a depth parameter to SerializeContextChain. size_t remaining_depth = depth;
context_ref.SerializeContextChain(); context_ref = context_ref.previous(&remaining_depth, true);
if (mode != kIgnoreSlot) { if (remaining_depth == 0 && mode != kIgnoreSlot) {
size_t remaining_depth = depth; ProcessImmutableLoad(context_ref, slot, mode);
context_ref = context_ref.previous(&remaining_depth);
if (remaining_depth == 0) {
ProcessImmutableLoad(context_ref, slot, mode);
}
} }
} }
} }
for (auto x : context_hints.virtual_contexts()) { for (auto x : context_hints.virtual_contexts()) {
if (x.distance <= static_cast<unsigned int>(depth)) { if (x.distance <= static_cast<unsigned int>(depth)) {
ContextRef context_ref(broker(), x.context); ContextRef context_ref(broker(), x.context);
// TODO(mvstanton): Add a depth parameter to SerializeContextChain. size_t remaining_depth = depth - x.distance;
context_ref.SerializeContextChain(); context_ref = context_ref.previous(&remaining_depth, true);
if (mode != kIgnoreSlot) { if (remaining_depth == 0 && mode != kIgnoreSlot) {
size_t remaining_depth = depth - x.distance; ProcessImmutableLoad(context_ref, slot, mode);
context_ref = context_ref.previous(&remaining_depth);
if (remaining_depth == 0) {
ProcessImmutableLoad(context_ref, slot, mode);
}
} }
} }
} }
...@@ -1437,7 +1427,7 @@ void SerializerForBackgroundCompilation::VisitCallJSRuntime( ...@@ -1437,7 +1427,7 @@ void SerializerForBackgroundCompilation::VisitCallJSRuntime(
// BytecodeGraphBuilder::VisitCallJSRuntime needs the {runtime_index} // BytecodeGraphBuilder::VisitCallJSRuntime needs the {runtime_index}
// slot in the native context to be serialized. // slot in the native context to be serialized.
const int runtime_index = iterator->GetNativeContextIndexOperand(0); const int runtime_index = iterator->GetNativeContextIndexOperand(0);
broker()->native_context().SerializeSlot(runtime_index); broker()->native_context().get(runtime_index, true);
} }
Hints SerializerForBackgroundCompilation::RunChildSerializer( Hints SerializerForBackgroundCompilation::RunChildSerializer(
......
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