Commit 58078730 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Teach the serializer about the closure register.

Rearrange things such that when creating the environment we have
access to the subject of compilation (either a full JSFunction or
just a FunctionBlueprint).

Bug: v8:7790
Change-Id: I03cc4701eb8bc1ed44c8381f4ab82da5f9b840b8
Reviewed-on: https://chromium-review.googlesource.com/c/1434374
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59091}
parent aaa38048
...@@ -15,6 +15,12 @@ namespace v8 { ...@@ -15,6 +15,12 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
CompilationSubject::CompilationSubject(Handle<JSFunction> closure,
Isolate* isolate)
: blueprint_{handle(closure->shared(), isolate),
handle(closure->feedback_vector(), isolate)},
closure_(closure) {}
Hints::Hints(Zone* zone) Hints::Hints(Zone* zone)
: constants_(zone), maps_(zone), function_blueprints_(zone) {} : constants_(zone), maps_(zone), function_blueprints_(zone) {}
...@@ -52,15 +58,11 @@ void Hints::Clear() { ...@@ -52,15 +58,11 @@ void Hints::Clear() {
class SerializerForBackgroundCompilation::Environment : public ZoneObject { class SerializerForBackgroundCompilation::Environment : public ZoneObject {
public: public:
explicit Environment(Zone* zone, Isolate* isolate, int register_count, Environment(Zone* zone, Isolate* isolate, CompilationSubject function);
int parameter_count); Environment(Zone* zone, Isolate* isolate, CompilationSubject function,
Environment(SerializerForBackgroundCompilation* serializer, Isolate* isolate,
int register_count, int parameter_count,
const HintsVector& arguments); const HintsVector& arguments);
int parameter_count() const { return parameter_count_; } FunctionBlueprint function() const { return function_; }
int register_count() const { return register_count_; }
Hints& accumulator_hints() { return environment_hints_[accumulator_index()]; } Hints& accumulator_hints() { return environment_hints_[accumulator_index()]; }
Hints& register_hints(interpreter::Register reg) { Hints& register_hints(interpreter::Register reg) {
...@@ -79,26 +81,25 @@ class SerializerForBackgroundCompilation::Environment : public ZoneObject { ...@@ -79,26 +81,25 @@ class SerializerForBackgroundCompilation::Environment : public ZoneObject {
HintsVector& dst); HintsVector& dst);
private: private:
explicit Environment(Zone* zone) int RegisterToLocalIndex(interpreter::Register reg) const;
: register_count_(0),
parameter_count_(0),
environment_hints_(zone),
return_value_hints_(zone) {}
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
int parameter_count() const { return parameter_count_; }
int register_count() const { return register_count_; }
int RegisterToLocalIndex(interpreter::Register reg) const; Zone* const zone_;
// Instead of storing the blueprint here, we could extract it from the
Zone* zone_; // (closure) hints but that would be cumbersome.
FunctionBlueprint const function_;
int const parameter_count_;
int const register_count_;
// environment_hints_ contains hints for the contents of the registers, // environment_hints_ contains hints for the contents of the registers,
// the accumulator and the parameters. The layout is as follows: // the accumulator and the parameters. The layout is as follows:
// [ receiver | parameters | registers | accumulator | context | closure ] // [ parameters | registers | accumulator | context | closure ]
const int register_count_; // The first parameter is the receiver.
const int parameter_count_;
HintsVector environment_hints_; HintsVector environment_hints_;
int register_base() const { return parameter_count_; } int accumulator_index() const { return parameter_count() + register_count(); }
int accumulator_index() const { return register_base() + register_count_; }
int current_context_index() const { return accumulator_index() + 1; } int current_context_index() const { return accumulator_index() + 1; }
int function_closure_index() const { return current_context_index() + 1; } int function_closure_index() const { return current_context_index() + 1; }
int environment_hints_size() const { return function_closure_index() + 1; } int environment_hints_size() const { return function_closure_index() + 1; }
...@@ -107,30 +108,36 @@ class SerializerForBackgroundCompilation::Environment : public ZoneObject { ...@@ -107,30 +108,36 @@ class SerializerForBackgroundCompilation::Environment : public ZoneObject {
}; };
SerializerForBackgroundCompilation::Environment::Environment( SerializerForBackgroundCompilation::Environment::Environment(
Zone* zone, Isolate* isolate, int register_count, int parameter_count) Zone* zone, Isolate* isolate, CompilationSubject function)
: zone_(zone), : zone_(zone),
register_count_(register_count), function_(function.blueprint()),
parameter_count_(parameter_count), parameter_count_(function_.shared->GetBytecodeArray()->parameter_count()),
register_count_(function_.shared->GetBytecodeArray()->register_count()),
environment_hints_(environment_hints_size(), Hints(zone), zone), environment_hints_(environment_hints_size(), Hints(zone), zone),
return_value_hints_(zone) {} return_value_hints_(zone) {
Handle<JSFunction> closure;
if (function.closure().ToHandle(&closure)) {
environment_hints_[function_closure_index()].AddConstant(closure);
} else {
environment_hints_[function_closure_index()].AddFunctionBlueprint(
function.blueprint());
}
}
SerializerForBackgroundCompilation::Environment::Environment( SerializerForBackgroundCompilation::Environment::Environment(
SerializerForBackgroundCompilation* serializer, Isolate* isolate, Zone* zone, Isolate* isolate, CompilationSubject function,
int register_count, int parameter_count, const HintsVector& arguments) const HintsVector& arguments)
: Environment(serializer->zone(), isolate, register_count, : Environment(zone, isolate, function) {
parameter_count) {
size_t param_count = static_cast<size_t>(parameter_count);
// Copy the hints for the actually passed arguments, at most up to // Copy the hints for the actually passed arguments, at most up to
// the parameter_count. // the parameter_count.
size_t param_count = static_cast<size_t>(parameter_count());
for (size_t i = 0; i < std::min(arguments.size(), param_count); ++i) { for (size_t i = 0; i < std::min(arguments.size(), param_count); ++i) {
environment_hints_[i] = arguments[i]; environment_hints_[i] = arguments[i];
} }
Hints undefined_hint(serializer->zone());
undefined_hint.AddConstant(
serializer->broker()->isolate()->factory()->undefined_value());
// Pad the rest with "undefined". // Pad the rest with "undefined".
Hints undefined_hint(zone);
undefined_hint.AddConstant(isolate->factory()->undefined_value());
for (size_t i = arguments.size(); i < param_count; ++i) { for (size_t i = arguments.size(); i < param_count; ++i) {
environment_hints_[i] = undefined_hint; environment_hints_[i] = undefined_hint;
} }
...@@ -138,57 +145,55 @@ SerializerForBackgroundCompilation::Environment::Environment( ...@@ -138,57 +145,55 @@ SerializerForBackgroundCompilation::Environment::Environment(
int SerializerForBackgroundCompilation::Environment::RegisterToLocalIndex( int SerializerForBackgroundCompilation::Environment::RegisterToLocalIndex(
interpreter::Register reg) const { interpreter::Register reg) const {
// TODO(mslekova): We also want to gather hints for the context and // TODO(mslekova): We also want to gather hints for the context.
// we already have data about the closure that we should record.
if (reg.is_current_context()) return current_context_index(); if (reg.is_current_context()) return current_context_index();
if (reg.is_function_closure()) return function_closure_index(); if (reg.is_function_closure()) return function_closure_index();
if (reg.is_parameter()) { if (reg.is_parameter()) {
return reg.ToParameterIndex(parameter_count()); return reg.ToParameterIndex(parameter_count());
} else { } else {
return register_base() + reg.index(); return parameter_count() + reg.index();
} }
} }
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, Zone* zone, Handle<JSFunction> function) JSHeapBroker* broker, Zone* zone, Handle<JSFunction> closure)
: broker_(broker), : broker_(broker),
zone_(zone), zone_(zone),
shared_(function->shared(), broker->isolate()), environment_(new (zone) Environment(zone, broker_->isolate(),
feedback_(function->feedback_vector(), broker->isolate()), {closure, broker_->isolate()})) {
environment_(new (zone) Environment( JSFunctionRef(broker, closure).Serialize();
zone, broker_->isolate(),
shared_->GetBytecodeArray()->register_count(),
shared_->GetBytecodeArray()->parameter_count())) {
JSFunctionRef(broker, function).Serialize();
} }
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, Zone* zone, FunctionBlueprint function, JSHeapBroker* broker, Zone* zone, CompilationSubject function,
const HintsVector& arguments) const HintsVector& arguments)
: broker_(broker), : broker_(broker),
zone_(zone), zone_(zone),
shared_(function.shared), environment_(new (zone) Environment(zone, broker_->isolate(), function,
feedback_(function.feedback), arguments)) {
environment_(new (zone) Environment( Handle<JSFunction> closure;
this, broker->isolate(), if (function.closure().ToHandle(&closure)) {
shared_->GetBytecodeArray()->register_count(), JSFunctionRef(broker, closure).Serialize();
shared_->GetBytecodeArray()->parameter_count(), arguments)) {} }
}
Hints SerializerForBackgroundCompilation::Run() { Hints SerializerForBackgroundCompilation::Run() {
SharedFunctionInfoRef shared(broker(), shared_); SharedFunctionInfoRef shared(broker(), environment()->function().shared);
FeedbackVectorRef feedback(broker(), feedback_); FeedbackVectorRef feedback_vector(broker(),
if (shared.IsSerializedForCompilation(feedback)) { environment()->function().feedback_vector);
if (shared.IsSerializedForCompilation(feedback_vector)) {
return Hints(zone()); return Hints(zone());
} }
shared.SetSerializedForCompilation(feedback); shared.SetSerializedForCompilation(feedback_vector);
feedback.SerializeSlots(); feedback_vector.SerializeSlots();
TraverseBytecode(); TraverseBytecode();
return environment()->return_value_hints(); return environment()->return_value_hints();
} }
void SerializerForBackgroundCompilation::TraverseBytecode() { void SerializerForBackgroundCompilation::TraverseBytecode() {
BytecodeArrayRef bytecode_array( BytecodeArrayRef bytecode_array(
broker(), handle(shared_->GetBytecodeArray(), broker()->isolate())); broker(), handle(environment()->function().shared->GetBytecodeArray(),
broker()->isolate()));
interpreter::BytecodeArrayIterator iterator(bytecode_array.object()); interpreter::BytecodeArrayIterator iterator(bytecode_array.object());
for (; !iterator.done(); iterator.Advance()) { for (; !iterator.done(); iterator.Advance()) {
...@@ -285,7 +290,8 @@ void SerializerForBackgroundCompilation::VisitCreateClosure( ...@@ -285,7 +290,8 @@ void SerializerForBackgroundCompilation::VisitCreateClosure(
SharedFunctionInfo::cast(iterator->GetConstantForIndexOperand(0)), SharedFunctionInfo::cast(iterator->GetConstantForIndexOperand(0)),
broker()->isolate()); broker()->isolate());
FeedbackNexus nexus(feedback_, iterator->GetSlotOperand(1)); FeedbackNexus nexus(environment()->function().feedback_vector,
iterator->GetSlotOperand(1));
Handle<Object> cell_value(nexus.GetFeedbackCell()->value(), Handle<Object> cell_value(nexus.GetFeedbackCell()->value(),
broker()->isolate()); broker()->isolate());
...@@ -420,7 +426,7 @@ void SerializerForBackgroundCompilation::VisitCallWithSpread( ...@@ -420,7 +426,7 @@ void SerializerForBackgroundCompilation::VisitCallWithSpread(
} }
Hints SerializerForBackgroundCompilation::RunChildSerializer( Hints SerializerForBackgroundCompilation::RunChildSerializer(
FunctionBlueprint function, const HintsVector& arguments, CompilationSubject function, const HintsVector& arguments,
bool with_spread) { bool with_spread) {
if (with_spread) { if (with_spread) {
DCHECK_LT(0, arguments.size()); DCHECK_LT(0, arguments.size());
...@@ -433,8 +439,9 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer( ...@@ -433,8 +439,9 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer(
HintsVector padded = arguments; HintsVector padded = arguments;
padded.pop_back(); // Remove the spread element. padded.pop_back(); // Remove the spread element.
// Fill the rest with empty hints. // Fill the rest with empty hints.
padded.resize(function.shared->GetBytecodeArray()->parameter_count(), padded.resize(
Hints(zone())); function.blueprint().shared->GetBytecodeArray()->parameter_count(),
Hints(zone()));
return RunChildSerializer(function, padded, false); return RunChildSerializer(function, padded, false);
} }
...@@ -453,20 +460,14 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct( ...@@ -453,20 +460,14 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
Handle<JSFunction> function = Handle<JSFunction>::cast(hint); Handle<JSFunction> function = Handle<JSFunction>::cast(hint);
if (!function->shared()->IsInlineable()) continue; if (!function->shared()->IsInlineable()) continue;
JSFunctionRef(broker(), function).Serialize(); environment()->accumulator_hints().Add(RunChildSerializer(
{function, broker()->isolate()}, arguments, with_spread));
Handle<SharedFunctionInfo> shared(function->shared(), broker()->isolate());
Handle<FeedbackVector> feedback(function->feedback_vector(),
broker()->isolate());
environment()->accumulator_hints().Add(
RunChildSerializer({shared, feedback}, arguments, with_spread));
} }
for (auto hint : callee.function_blueprints()) { for (auto hint : callee.function_blueprints()) {
if (!hint.shared->IsInlineable()) continue; if (!hint.shared->IsInlineable()) continue;
environment()->accumulator_hints().Add( environment()->accumulator_hints().Add(
RunChildSerializer(hint, arguments, with_spread)); RunChildSerializer(CompilationSubject(hint), arguments, with_spread));
} }
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_COMPILER_SERIALIZER_FOR_BACKGROUND_COMPILATION_H_ #define V8_COMPILER_SERIALIZER_FOR_BACKGROUND_COMPILATION_H_
#include "src/handles.h" #include "src/handles.h"
#include "src/maybe-handles.h"
#include "src/zone/zone-containers.h" #include "src/zone/zone-containers.h"
namespace v8 { namespace v8 {
...@@ -110,7 +111,21 @@ class JSHeapBroker; ...@@ -110,7 +111,21 @@ class JSHeapBroker;
struct FunctionBlueprint { struct FunctionBlueprint {
Handle<SharedFunctionInfo> shared; Handle<SharedFunctionInfo> shared;
Handle<FeedbackVector> feedback; Handle<FeedbackVector> feedback_vector;
};
class CompilationSubject {
public:
explicit CompilationSubject(FunctionBlueprint blueprint)
: blueprint_(blueprint) {}
CompilationSubject(Handle<JSFunction> closure, Isolate* isolate);
FunctionBlueprint blueprint() const { return blueprint_; }
MaybeHandle<JSFunction> closure() const { return closure_; }
private:
FunctionBlueprint blueprint_;
MaybeHandle<JSFunction> closure_;
}; };
class Hints { class Hints {
...@@ -143,12 +158,12 @@ typedef ZoneVector<Hints> HintsVector; ...@@ -143,12 +158,12 @@ typedef ZoneVector<Hints> HintsVector;
class SerializerForBackgroundCompilation { class SerializerForBackgroundCompilation {
public: public:
SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone, SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone,
Handle<JSFunction> function); Handle<JSFunction> closure);
Hints Run(); // NOTE: Returns empty for an already-serialized function. Hints Run(); // NOTE: Returns empty for an already-serialized function.
private: private:
SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone, SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone,
FunctionBlueprint function, CompilationSubject function,
const HintsVector& arguments); const HintsVector& arguments);
void TraverseBytecode(); void TraverseBytecode();
...@@ -160,24 +175,22 @@ class SerializerForBackgroundCompilation { ...@@ -160,24 +175,22 @@ class SerializerForBackgroundCompilation {
class Environment; class Environment;
Zone* zone() const { return zone_; }
JSHeapBroker* broker() const { return broker_; }
Environment* environment() const { return environment_; }
void ProcessCallOrConstruct(const Hints& callee, const HintsVector& arguments, void ProcessCallOrConstruct(const Hints& callee, const HintsVector& arguments,
bool with_spread = false); bool with_spread = false);
void ProcessCallVarArgs(interpreter::BytecodeArrayIterator* iterator, void ProcessCallVarArgs(interpreter::BytecodeArrayIterator* iterator,
ConvertReceiverMode receiver_mode, ConvertReceiverMode receiver_mode,
bool with_spread = false); bool with_spread = false);
Hints RunChildSerializer(FunctionBlueprint function, Hints RunChildSerializer(CompilationSubject function,
const HintsVector& arguments, bool with_spread); const HintsVector& arguments, bool with_spread);
JSHeapBroker* broker_; JSHeapBroker* broker() const { return broker_; }
Zone* zone_; Zone* zone() const { return zone_; }
Handle<SharedFunctionInfo> shared_; Environment* environment() const { return environment_; }
Handle<FeedbackVector> feedback_;
Environment* environment_; JSHeapBroker* const broker_;
Zone* const zone_;
Environment* const environment_;
}; };
} // namespace compiler } // namespace compiler
......
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