[Turbofan] Wiser zone allocation for child serializers

The serialization step in the pipeline gets an initial zone, and thus
far, it's allocated all of it's hinting information in that zone.
However, much of this comes from stepping into calls and
walking the bytecode of the called function. Once we finished
recursing into a call, we should be able to throw all those
hints away -- they've served their purpose, and the "output"
of their work is a set of new objects made visible to the broker.

Therefore, we should create and destroy a child zone.

On a run of typescript, this reduces absolute max (high water mark)
allocation of the serialization phase from 10 MB to 5 MB.

Bug: v8:7790
Change-Id: Icbb35abed28b1a924328541df82be23594152a8f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1800570
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63872}
This commit is contained in:
Mike Stanton 2019-09-18 15:48:21 +02:00 committed by Commit Bot
parent c45c2b9ced
commit 3c3bd14791
4 changed files with 74 additions and 38 deletions

View File

@ -1430,9 +1430,9 @@ struct SerializationPhase {
flags |=
SerializerForBackgroundCompilationFlag::kAnalyzeEnvironmentLiveness;
}
RunSerializerForBackgroundCompilation(data->broker(), data->dependencies(),
temp_zone, data->info()->closure(),
flags, data->info()->osr_offset());
RunSerializerForBackgroundCompilation(
data->zone_stats(), data->broker(), data->dependencies(),
data->info()->closure(), flags, data->info()->osr_offset());
if (data->specialization_context().IsJust()) {
ContextRef(data->broker(),
data->specialization_context().FromJust().context);

View File

@ -12,6 +12,7 @@
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/functional-list.h"
#include "src/compiler/js-heap-broker.h"
#include "src/compiler/zone-stats.h"
#include "src/handles/handles-inl.h"
#include "src/ic/call-optimization.h"
#include "src/interpreter/bytecode-array-iterator.h"
@ -304,6 +305,7 @@ class Hints {
void AddVirtualContext(VirtualContext virtual_context, Zone* zone);
void Add(const Hints& other, Zone* zone);
void AddFromChildSerializer(const Hints& other, Zone* zone);
void Clear();
bool IsEmpty() const;
@ -371,18 +373,18 @@ class CompilationSubject {
class SerializerForBackgroundCompilation {
public:
SerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
Handle<JSFunction> closure, SerializerForBackgroundCompilationFlags flags,
BailoutId osr_offset);
ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, Handle<JSFunction> closure,
SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset);
Hints Run(); // NOTE: Returns empty for an already-serialized function.
class Environment;
private:
SerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
CompilationSubject function, base::Optional<Hints> new_target,
const HintsVector& arguments,
ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, CompilationSubject function,
base::Optional<Hints> new_target, const HintsVector& arguments,
SerializerForBackgroundCompilationFlags flags);
bool BailoutOnUninitialized(ProcessedFeedback const& feedback);
@ -504,14 +506,14 @@ class SerializerForBackgroundCompilation {
JSHeapBroker* broker() const { return broker_; }
CompilationDependencies* dependencies() const { return dependencies_; }
Zone* zone() const { return zone_; }
Zone* zone() { return zone_scope_.zone(); }
Environment* environment() const { return environment_; }
SerializerForBackgroundCompilationFlags flags() const { return flags_; }
BailoutId osr_offset() const { return osr_offset_; }
JSHeapBroker* const broker_;
CompilationDependencies* const dependencies_;
Zone* const zone_;
ZoneStats::Scope zone_scope_;
Environment* const environment_;
ZoneUnorderedMap<int, Environment*> jump_target_environments_;
SerializerForBackgroundCompilationFlags const flags_;
@ -519,11 +521,11 @@ class SerializerForBackgroundCompilation {
};
void RunSerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
Handle<JSFunction> closure, SerializerForBackgroundCompilationFlags flags,
BailoutId osr_offset) {
SerializerForBackgroundCompilation serializer(broker, dependencies, zone,
closure, flags, osr_offset);
ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, Handle<JSFunction> closure,
SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset) {
SerializerForBackgroundCompilation serializer(
zone_stats, broker, dependencies, closure, flags, osr_offset);
serializer.Run();
}
@ -534,13 +536,18 @@ FunctionBlueprint::FunctionBlueprint(Handle<SharedFunctionInfo> shared,
const Hints& context_hints)
: shared_(shared),
feedback_vector_(feedback_vector),
context_hints_(context_hints) {}
context_hints_(context_hints) {
// The checked invariant rules out recursion and thus avoids complexity.
CHECK(context_hints_.function_blueprints().IsEmpty());
}
FunctionBlueprint::FunctionBlueprint(Handle<JSFunction> function,
Isolate* isolate, Zone* zone)
: shared_(handle(function->shared(), isolate)),
feedback_vector_(handle(function->feedback_vector(), isolate)),
context_hints_() {
// The checked invariant rules out recursion and thus avoids complexity.
CHECK(context_hints_.function_blueprints().IsEmpty());
context_hints_.AddConstant(handle(function->context(), isolate), zone);
}
@ -601,6 +608,24 @@ void Hints::Add(const Hints& other, Zone* zone) {
for (auto x : other.virtual_contexts()) AddVirtualContext(x, zone);
}
void Hints::AddFromChildSerializer(const Hints& other, Zone* zone) {
for (auto x : other.constants()) AddConstant(x, zone);
for (auto x : other.maps()) AddMap(x, zone);
for (auto x : other.virtual_contexts()) AddVirtualContext(x, zone);
// Adding hints from a child serializer run means copying data out from
// a zone that's being destroyed. FunctionBlueprints have zone allocated
// data, so we've got to make a deep copy to eliminate traces of the
// dying zone.
for (auto x : other.function_blueprints()) {
Hints new_blueprint_hints;
new_blueprint_hints.AddFromChildSerializer(x.context_hints(), zone);
FunctionBlueprint new_blueprint(x.shared(), x.feedback_vector(),
new_blueprint_hints);
AddFunctionBlueprint(new_blueprint, zone);
}
}
bool Hints::IsEmpty() const {
return constants().IsEmpty() && maps().IsEmpty() &&
function_blueprints().IsEmpty() && virtual_contexts().IsEmpty();
@ -860,30 +885,31 @@ int SerializerForBackgroundCompilation::Environment::RegisterToLocalIndex(
}
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
Handle<JSFunction> closure, SerializerForBackgroundCompilationFlags flags,
BailoutId osr_offset)
ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, Handle<JSFunction> closure,
SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset)
: broker_(broker),
dependencies_(dependencies),
zone_(zone),
environment_(new (zone) Environment(
zone, CompilationSubject(closure, broker_->isolate(), zone))),
jump_target_environments_(zone),
zone_scope_(zone_stats, ZONE_NAME),
environment_(new (zone()) Environment(
zone(), CompilationSubject(closure, broker_->isolate(), zone()))),
jump_target_environments_(zone()),
flags_(flags),
osr_offset_(osr_offset) {
JSFunctionRef(broker, closure).Serialize();
}
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
CompilationSubject function, base::Optional<Hints> new_target,
const HintsVector& arguments, SerializerForBackgroundCompilationFlags flags)
ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, CompilationSubject function,
base::Optional<Hints> new_target, const HintsVector& arguments,
SerializerForBackgroundCompilationFlags flags)
: broker_(broker),
dependencies_(dependencies),
zone_(zone),
environment_(new (zone) Environment(zone, broker_->isolate(), function,
new_target, arguments)),
jump_target_environments_(zone),
zone_scope_(zone_stats, ZONE_NAME),
environment_(new (zone()) Environment(zone(), broker_->isolate(),
function, new_target, arguments)),
jump_target_environments_(zone()),
flags_(flags),
osr_offset_(BailoutId::None()) {
TraceScope tracer(
@ -1722,10 +1748,17 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer(
return RunChildSerializer(function, new_target, padded, false);
}
Hints hints;
{
// The Hints returned by the call to Run are allocated in the zone
// created by the child serializer. Adding those hints to a hints
// object created in our zone will preserve the information.
SerializerForBackgroundCompilation child_serializer(
broker(), dependencies(), zone(), function, new_target, arguments,
flags());
return child_serializer.Run();
zone_scope_.zone_stats(), broker(), dependencies(), function,
new_target, arguments, flags());
hints.AddFromChildSerializer(child_serializer.Run(), zone());
}
return hints;
}
bool SerializerForBackgroundCompilation::ProcessSFIForCallOrConstruct(

View File

@ -17,6 +17,7 @@ namespace compiler {
class CompilationDependencies;
class JSHeapBroker;
class ZoneStats;
enum class SerializerForBackgroundCompilationFlag : uint8_t {
kBailoutOnUninitialized = 1 << 0,
@ -27,9 +28,9 @@ using SerializerForBackgroundCompilationFlags =
base::Flags<SerializerForBackgroundCompilationFlag>;
void RunSerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
Handle<JSFunction> closure, SerializerForBackgroundCompilationFlags flags,
BailoutId osr_offset);
ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, Handle<JSFunction> closure,
SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset);
} // namespace compiler
} // namespace internal

View File

@ -33,6 +33,8 @@ class V8_EXPORT_PRIVATE ZoneStats final {
zone_ = nullptr;
}
ZoneStats* zone_stats() const { return zone_stats_; }
private:
const char* zone_name_;
ZoneStats* const zone_stats_;