Commit a75b129a authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[TurboFan] Only serialize JSFunction feedback and code if needed.

The feedback_vector/cell and code fields of a JSFunctionRef are only
used when generating code for the function (e.g., for the function
being optimized or inlined functions). This CL explicitly serializes
these fields only when the function will be used for codegen, otherwise
avoiding their serialization.

BUG=v8:7790,v8:9684

Change-Id: If76bc0b77e51aa10517699e0a9198358fe77f009
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2617083Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72129}
parent d7f767e1
...@@ -355,10 +355,15 @@ class V8_EXPORT_PRIVATE JSFunctionRef : public JSObjectRef { ...@@ -355,10 +355,15 @@ class V8_EXPORT_PRIVATE JSFunctionRef : public JSObjectRef {
ContextRef context() const; ContextRef context() const;
NativeContextRef native_context() const; NativeContextRef native_context() const;
SharedFunctionInfoRef shared() const; SharedFunctionInfoRef shared() const;
int InitialMapInstanceSizeWithMinSlack() const;
void SerializeCodeAndFeedback();
bool serialized_code_and_feedback() const;
// The following are available only after calling SerializeCodeAndFeedback().
FeedbackVectorRef feedback_vector() const; FeedbackVectorRef feedback_vector() const;
FeedbackCellRef raw_feedback_cell() const; FeedbackCellRef raw_feedback_cell() const;
CodeRef code() const; CodeRef code() const;
int InitialMapInstanceSizeWithMinSlack() const;
}; };
class JSRegExpRef : public JSObjectRef { class JSRegExpRef : public JSObjectRef {
......
...@@ -607,14 +607,28 @@ class JSFunctionData : public JSObjectData { ...@@ -607,14 +607,28 @@ class JSFunctionData : public JSObjectData {
void Serialize(JSHeapBroker* broker); void Serialize(JSHeapBroker* broker);
bool serialized() const { return serialized_; } bool serialized() const { return serialized_; }
void SerializeCodeAndFeedback(JSHeapBroker* broker);
bool serialized_code_and_feedback() const {
return serialized_code_and_feedback_;
}
ObjectData* context() const { return context_; } ObjectData* context() const { return context_; }
ObjectData* native_context() const { return native_context_; } ObjectData* native_context() const { return native_context_; }
ObjectData* initial_map() const { return initial_map_; } ObjectData* initial_map() const { return initial_map_; }
ObjectData* prototype() const { return prototype_; } ObjectData* prototype() const { return prototype_; }
ObjectData* shared() const { return shared_; } ObjectData* shared() const { return shared_; }
ObjectData* raw_feedback_cell() const { return feedback_cell_; } ObjectData* raw_feedback_cell() const {
ObjectData* feedback_vector() const { return feedback_vector_; } DCHECK(serialized_code_and_feedback());
ObjectData* code() const { return code_; } return feedback_cell_;
}
ObjectData* feedback_vector() const {
DCHECK(serialized_code_and_feedback());
return feedback_vector_;
}
ObjectData* code() const {
DCHECK(serialized_code_and_feedback());
return code_;
}
int initial_map_instance_size_with_min_slack() const { int initial_map_instance_size_with_min_slack() const {
CHECK(serialized_); CHECK(serialized_);
return initial_map_instance_size_with_min_slack_; return initial_map_instance_size_with_min_slack_;
...@@ -628,6 +642,7 @@ class JSFunctionData : public JSObjectData { ...@@ -628,6 +642,7 @@ class JSFunctionData : public JSObjectData {
bool PrototypeRequiresRuntimeLookup_; bool PrototypeRequiresRuntimeLookup_;
bool serialized_ = false; bool serialized_ = false;
bool serialized_code_and_feedback_ = false;
ObjectData* context_ = nullptr; ObjectData* context_ = nullptr;
ObjectData* native_context_ = nullptr; ObjectData* native_context_ = nullptr;
...@@ -1250,18 +1265,11 @@ void JSFunctionData::Serialize(JSHeapBroker* broker) { ...@@ -1250,18 +1265,11 @@ void JSFunctionData::Serialize(JSHeapBroker* broker) {
DCHECK_NULL(initial_map_); DCHECK_NULL(initial_map_);
DCHECK_NULL(prototype_); DCHECK_NULL(prototype_);
DCHECK_NULL(shared_); DCHECK_NULL(shared_);
DCHECK_NULL(feedback_cell_);
DCHECK_NULL(feedback_vector_);
DCHECK_NULL(code_);
context_ = broker->GetOrCreateData(function->context()); context_ = broker->GetOrCreateData(function->context());
native_context_ = broker->GetOrCreateData(function->native_context()); native_context_ = broker->GetOrCreateData(function->native_context());
shared_ = broker->GetOrCreateData(function->shared()); shared_ = broker->GetOrCreateData(function->shared());
feedback_cell_ = broker->GetOrCreateData(function->raw_feedback_cell());
feedback_vector_ = has_feedback_vector()
? broker->GetOrCreateData(function->feedback_vector())
: nullptr;
code_ = broker->GetOrCreateData(function->code());
initial_map_ = has_initial_map() initial_map_ = has_initial_map()
? broker->GetOrCreateData(function->initial_map()) ? broker->GetOrCreateData(function->initial_map())
: nullptr; : nullptr;
...@@ -1284,6 +1292,24 @@ void JSFunctionData::Serialize(JSHeapBroker* broker) { ...@@ -1284,6 +1292,24 @@ void JSFunctionData::Serialize(JSHeapBroker* broker) {
} }
} }
void JSFunctionData::SerializeCodeAndFeedback(JSHeapBroker* broker) {
DCHECK(serialized_);
if (serialized_code_and_feedback_) return;
serialized_code_and_feedback_ = true;
TraceScope tracer(broker, this, "JSFunctionData::SerializeCodeAndFeedback");
Handle<JSFunction> function = Handle<JSFunction>::cast(object());
DCHECK_NULL(feedback_cell_);
DCHECK_NULL(feedback_vector_);
DCHECK_NULL(code_);
code_ = broker->GetOrCreateData(function->code());
feedback_cell_ = broker->GetOrCreateData(function->raw_feedback_cell());
feedback_vector_ = has_feedback_vector()
? broker->GetOrCreateData(function->feedback_vector())
: nullptr;
}
void MapData::SerializeElementsKindGeneralizations(JSHeapBroker* broker) { void MapData::SerializeElementsKindGeneralizations(JSHeapBroker* broker) {
if (serialized_elements_kind_generalizations_) return; if (serialized_elements_kind_generalizations_) return;
serialized_elements_kind_generalizations_ = true; serialized_elements_kind_generalizations_ = true;
...@@ -4061,6 +4087,12 @@ void JSFunctionRef::Serialize() { ...@@ -4061,6 +4087,12 @@ void JSFunctionRef::Serialize() {
data()->AsJSFunction()->Serialize(broker()); data()->AsJSFunction()->Serialize(broker());
} }
void JSFunctionRef::SerializeCodeAndFeedback() {
if (data_->should_access_heap()) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsJSFunction()->SerializeCodeAndFeedback(broker());
}
bool JSBoundFunctionRef::serialized() const { bool JSBoundFunctionRef::serialized() const {
if (data_->should_access_heap()) return true; if (data_->should_access_heap()) return true;
return data()->AsJSBoundFunction()->serialized(); return data()->AsJSBoundFunction()->serialized();
...@@ -4071,6 +4103,11 @@ bool JSFunctionRef::serialized() const { ...@@ -4071,6 +4103,11 @@ bool JSFunctionRef::serialized() const {
return data()->AsJSFunction()->serialized(); return data()->AsJSFunction()->serialized();
} }
bool JSFunctionRef::serialized_code_and_feedback() const {
if (data_->should_access_heap()) return true;
return data()->AsJSFunction()->serialized_code_and_feedback();
}
void SharedFunctionInfoRef::SerializeFunctionTemplateInfo() { void SharedFunctionInfoRef::SerializeFunctionTemplateInfo() {
if (data_->should_access_heap()) return; if (data_->should_access_heap()) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing); CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
......
...@@ -44,7 +44,6 @@ bool CanConsiderForInlining(JSHeapBroker* broker, ...@@ -44,7 +44,6 @@ bool CanConsiderForInlining(JSHeapBroker* broker,
<< feedback_vector << " (missing data)"); << feedback_vector << " (missing data)");
return false; return false;
} }
TRACE("Considering " << shared << " for inlining with " << feedback_vector); TRACE("Considering " << shared << " for inlining with " << feedback_vector);
return true; return true;
} }
...@@ -57,12 +56,13 @@ bool CanConsiderForInlining(JSHeapBroker* broker, ...@@ -57,12 +56,13 @@ bool CanConsiderForInlining(JSHeapBroker* broker,
return false; return false;
} }
if (!function.serialized()) { if (!function.serialized() || !function.serialized_code_and_feedback()) {
TRACE_BROKER_MISSING( TRACE_BROKER_MISSING(
broker, "data for " << function << " (cannot consider for inlining)"); broker, "data for " << function << " (cannot consider for inlining)");
TRACE("Cannot consider " << function << " for inlining (missing data)"); TRACE("Cannot consider " << function << " for inlining (missing data)");
return false; return false;
} }
return CanConsiderForInlining(broker, function.shared(), return CanConsiderForInlining(broker, function.shared(),
function.feedback_vector()); function.feedback_vector());
} }
......
...@@ -1070,6 +1070,7 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( ...@@ -1070,6 +1070,7 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
arguments_(zone()) { arguments_(zone()) {
closure_hints_.AddConstant(closure, zone(), broker_); closure_hints_.AddConstant(closure, zone(), broker_);
JSFunctionRef(broker, closure).Serialize(); JSFunctionRef(broker, closure).Serialize();
JSFunctionRef(broker, closure).SerializeCodeAndFeedback();
TRACE_BROKER(broker_, "Hints for <closure>: " << closure_hints_); TRACE_BROKER(broker_, "Hints for <closure>: " << closure_hints_);
TRACE_BROKER(broker_, "Initial environment:\n" << *environment_); TRACE_BROKER(broker_, "Initial environment:\n" << *environment_);
...@@ -1097,6 +1098,7 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( ...@@ -1097,6 +1098,7 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
if (function.closure().ToHandle(&closure)) { if (function.closure().ToHandle(&closure)) {
closure_hints_.AddConstant(closure, zone(), broker); closure_hints_.AddConstant(closure, zone(), broker);
JSFunctionRef(broker, closure).Serialize(); JSFunctionRef(broker, closure).Serialize();
JSFunctionRef(broker, closure).SerializeCodeAndFeedback();
} else { } else {
closure_hints_.AddVirtualClosure(function.virtual_closure(), zone(), closure_hints_.AddVirtualClosure(function.virtual_closure(), zone(),
broker); broker);
......
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