Commit 31da5d19 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[turbofan] Analysis of the broker Refs distribution

This analysis shows the number of used/unused refs
as well as their by-type distribution and outputs the broker zone
memory. It introduces a new flag --trace-heap-broker-memory.

Doc: https://docs.google.com/document/d/1oUMxlC2YbficEVkQ1X8TK9WNCWRmLqzDRFy4z3cJsII/edit#heading=h.3sde9siqk2yw

Bug: v8:9720
Change-Id: I4fafc225134d0548e976ce00d67bd5cabeda60c3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1849526
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64269}
parent 4a1a23f0
......@@ -87,6 +87,11 @@ class ObjectData : public ZoneObject {
ObjectDataKind kind() const { return kind_; }
bool is_smi() const { return kind_ == kSmi; }
#ifdef DEBUG
enum class Usage{kUnused, kOnlyIdentityUsed, kDataUsed};
mutable Usage used_status = Usage::kUnused;
#endif // DEBUG
private:
Handle<Object> const object_;
ObjectDataKind const kind_;
......@@ -2190,6 +2195,12 @@ void JSRegExpData::SerializeAsRegExpBoilerplate(JSHeapBroker* broker) {
}
bool ObjectRef::equals(const ObjectRef& other) const {
#ifdef DEBUG
if (broker()->mode() == JSHeapBroker::kSerialized &&
data_->used_status == ObjectData::Usage::kUnused) {
data_->used_status = ObjectData::Usage::kOnlyIdentityUsed;
}
#endif // DEBUG
return data_ == other.data_;
}
......@@ -2249,7 +2260,7 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone,
TRACE(this, "Constructing heap broker");
}
std::ostream& JSHeapBroker::Trace() {
std::ostream& JSHeapBroker::Trace() const {
return trace_out_ << "[" << this << "] "
<< std::string(trace_indentation_ * 2, ' ');
}
......@@ -2260,10 +2271,92 @@ void JSHeapBroker::StopSerializing() {
mode_ = kSerialized;
}
#ifdef DEBUG
void JSHeapBroker::PrintRefsAnalysis() const {
// Usage counts
size_t used_total = 0, unused_total = 0, identity_used_total = 0;
for (RefsMap::Entry* ref = refs_->Start(); ref != nullptr;
ref = refs_->Next(ref)) {
switch (ref->value->used_status) {
case ObjectData::Usage::kUnused:
++unused_total;
break;
case ObjectData::Usage::kOnlyIdentityUsed:
++identity_used_total;
break;
case ObjectData::Usage::kDataUsed:
++used_total;
break;
}
}
// Ref types analysis
TRACE_BROKER_MEMORY(
this, "Refs: " << refs_->occupancy() << "; data used: " << used_total
<< "; only identity used: " << identity_used_total
<< "; unused: " << unused_total);
size_t used_smis = 0, unused_smis = 0, identity_used_smis = 0;
size_t used[LAST_TYPE + 1] = {0};
size_t unused[LAST_TYPE + 1] = {0};
size_t identity_used[LAST_TYPE + 1] = {0};
for (RefsMap::Entry* ref = refs_->Start(); ref != nullptr;
ref = refs_->Next(ref)) {
if (ref->value->is_smi()) {
switch (ref->value->used_status) {
case ObjectData::Usage::kUnused:
++unused_smis;
break;
case ObjectData::Usage::kOnlyIdentityUsed:
++identity_used_smis;
break;
case ObjectData::Usage::kDataUsed:
++used_smis;
break;
}
} else {
InstanceType instance_type =
static_cast<const HeapObjectData*>(ref->value)
->map()
->instance_type();
CHECK_LE(FIRST_TYPE, instance_type);
CHECK_LE(instance_type, LAST_TYPE);
switch (ref->value->used_status) {
case ObjectData::Usage::kUnused:
++unused[instance_type];
break;
case ObjectData::Usage::kOnlyIdentityUsed:
++identity_used[instance_type];
break;
case ObjectData::Usage::kDataUsed:
++used[instance_type];
break;
}
}
}
TRACE_BROKER_MEMORY(
this, "Smis: " << used_smis + identity_used_smis + unused_smis
<< "; data used: " << used_smis << "; only identity used: "
<< identity_used_smis << "; unused: " << unused_smis);
for (uint16_t i = FIRST_TYPE; i <= LAST_TYPE; ++i) {
size_t total = used[i] + identity_used[i] + unused[i];
if (total == 0) continue;
TRACE_BROKER_MEMORY(
this, InstanceType(i) << ": " << total << "; data used: " << used[i]
<< "; only identity used: " << identity_used[i]
<< "; unused: " << unused[i]);
}
}
#endif // DEBUG
void JSHeapBroker::Retire() {
CHECK_EQ(mode_, kSerialized);
TRACE(this, "Retiring");
mode_ = kRetired;
#ifdef DEBUG
PrintRefsAnalysis();
#endif // DEBUG
}
bool JSHeapBroker::SerializingAllowed() const { return mode() == kSerializing; }
......@@ -3754,12 +3847,32 @@ void JSRegExpRef::SerializeAsRegExpBoilerplate() {
JSObjectRef::data()->AsJSRegExp()->SerializeAsRegExpBoilerplate(broker());
}
Handle<Object> ObjectRef::object() const { return data_->object(); }
Handle<Object> ObjectRef::object() const {
#ifdef DEBUG
if (broker()->mode() == JSHeapBroker::kSerialized &&
data_->used_status == ObjectData::Usage::kUnused) {
data_->used_status = ObjectData::Usage::kOnlyIdentityUsed;
}
#endif // DEBUG
return data_->object();
}
#ifdef DEBUG
#define DEF_OBJECT_GETTER(T) \
Handle<T> T##Ref::object() const { \
if (broker()->mode() == JSHeapBroker::kSerialized && \
data_->used_status == ObjectData::Usage::kUnused) { \
data_->used_status = ObjectData::Usage::kOnlyIdentityUsed; \
} \
return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
}
#else
#define DEF_OBJECT_GETTER(T) \
Handle<T> T##Ref::object() const { \
return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
}
#endif // DEBUG
HEAP_BROKER_OBJECT_LIST(DEF_OBJECT_GETTER)
#undef DEF_OBJECT_GETTER
......@@ -3771,7 +3884,12 @@ ObjectData* ObjectRef::data() const {
CHECK_NE(data_->kind(), kSerializedHeapObject);
return data_;
case JSHeapBroker::kSerializing:
CHECK_NE(data_->kind(), kUnserializedHeapObject);
return data_;
case JSHeapBroker::kSerialized:
#ifdef DEBUG
data_->used_status = ObjectData::Usage::kDataUsed;
#endif // DEBUG
CHECK_NE(data_->kind(), kUnserializedHeapObject);
return data_;
case JSHeapBroker::kRetired:
......
......@@ -34,6 +34,12 @@ std::ostream& operator<<(std::ostream& os, const ObjectRef& ref);
broker->Trace() << x << '\n'; \
} while (false)
#define TRACE_BROKER_MEMORY(broker, x) \
do { \
if (broker->tracing_enabled() && FLAG_trace_heap_broker_memory) \
broker->Trace() << x << std::endl; \
} while (false)
#define TRACE_BROKER_MISSING(broker, x) \
do { \
if (broker->tracing_enabled()) \
......@@ -86,6 +92,10 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
void Retire();
bool SerializingAllowed() const;
#ifdef DEBUG
void PrintRefsAnalysis() const;
#endif // DEBUG
// Returns nullptr iff handle unknown.
ObjectData* GetData(Handle<Object>) const;
// Never returns nullptr.
......@@ -169,7 +179,7 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
StringRef GetTypedArrayStringTag(ElementsKind kind);
std::ostream& Trace();
std::ostream& Trace() const;
void IncrementTracingIndentation();
void DecrementTracingIndentation();
......@@ -217,7 +227,7 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
array_and_object_prototypes_;
BrokerMode mode_ = kDisabled;
bool const tracing_enabled_;
StdoutStream trace_out_;
mutable StdoutStream trace_out_;
unsigned trace_indentation_ = 0;
PerIsolateCompilerCache* compiler_cache_ = nullptr;
ZoneUnorderedMap<FeedbackSource, ProcessedFeedback const*,
......
......@@ -1009,6 +1009,8 @@ bool SerializerForBackgroundCompilation::BailoutOnUninitialized(
Hints SerializerForBackgroundCompilation::Run() {
TraceScope tracer(broker(), this, "SerializerForBackgroundCompilation::Run");
TRACE_BROKER_MEMORY(broker(), "[serializer start] Broker zone usage: "
<< broker()->zone()->allocation_size());
SharedFunctionInfoRef shared(broker(), environment()->function().shared());
FeedbackVectorRef feedback_vector_ref(broker(), feedback_vector());
if (shared.IsSerializedForCompilation(feedback_vector_ref)) {
......@@ -1030,6 +1032,9 @@ Hints SerializerForBackgroundCompilation::Run() {
feedback_vector_ref.Serialize();
TraverseBytecode();
TRACE_BROKER_MEMORY(broker(), "[serializer end] Broker zone usage: "
<< broker()->zone()->allocation_size());
return environment()->return_value_hints();
}
......
......@@ -487,9 +487,12 @@ DEFINE_BOOL(concurrent_inlining, false,
DEFINE_IMPLICATION(future, concurrent_inlining)
DEFINE_BOOL(trace_heap_broker_verbose, false,
"trace the heap broker verbosely (all reports)")
DEFINE_BOOL(trace_heap_broker_memory, false,
"trace the heap broker memory (refs analysis and zone numbers)")
DEFINE_BOOL(trace_heap_broker, false,
"trace the heap broker (reports on missing data only)")
DEFINE_IMPLICATION(trace_heap_broker_verbose, trace_heap_broker)
DEFINE_IMPLICATION(trace_heap_broker_memory, trace_heap_broker)
// Flags for stress-testing the compiler.
DEFINE_INT(stress_runs, 0, "number of stress runs")
......
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