Commit 83dee31e authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[Parser] Split building logic out of ProducedPreParserScopeData.

Splits PreParsedScopeDataBuilder out of ProducedPreParserScopeData to make the split between
building PreParsedScopeData and using already build PreParserScopeData more explicit.

BUG=v8:8041

Change-Id: Iab42cab84c247152c14ac39f3136f985753160ec
Reviewed-on: https://chromium-review.googlesource.com/1202104
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55718}
parent ce589362
......@@ -319,7 +319,7 @@ void DeclarationScope::SetDefaults() {
should_eager_compile_ = false;
was_lazily_parsed_ = false;
is_skipped_function_ = false;
produced_preparsed_scope_data_ = nullptr;
preparsed_scope_data_builder_ = nullptr;
#ifdef DEBUG
DeclarationScope* outer_declaration_scope =
outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
......@@ -1532,7 +1532,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
void Scope::SavePreParsedScopeData() {
DCHECK(FLAG_preparser_scope_analysis);
if (ProducedPreParsedScopeData::ScopeIsSkippableFunctionScope(this)) {
if (PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(this)) {
AsDeclarationScope()->SavePreParsedScopeDataForDeclarationScope();
}
......@@ -1542,9 +1542,9 @@ void Scope::SavePreParsedScopeData() {
}
void DeclarationScope::SavePreParsedScopeDataForDeclarationScope() {
if (produced_preparsed_scope_data_ != nullptr) {
if (preparsed_scope_data_builder_ != nullptr) {
DCHECK(FLAG_preparser_scope_analysis);
produced_preparsed_scope_data_->SaveScopeAllocationData(this);
preparsed_scope_data_builder_->SaveScopeAllocationData(this);
}
}
......@@ -1554,8 +1554,8 @@ void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
if (!outer_scope_->is_script_scope() ||
(FLAG_preparser_scope_analysis &&
produced_preparsed_scope_data_ != nullptr &&
produced_preparsed_scope_data_->ContainsInnerFunctions())) {
preparsed_scope_data_builder_ != nullptr &&
preparsed_scope_data_builder_->ContainsInnerFunctions())) {
// Try to resolve unresolved variables for this Scope and migrate those
// which cannot be resolved inside. It doesn't make sense to try to resolve
// them in the outer Scopes here, because they are incomplete.
......
......@@ -20,8 +20,7 @@ class AstValueFactory;
class AstRawString;
class Declaration;
class ParseInfo;
class PreParsedScopeData;
class ProducedPreParsedScopeData;
class PreParsedScopeDataBuilder;
class SloppyBlockFunctionStatement;
class Statement;
class StringSet;
......@@ -919,13 +918,13 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// saved in produced_preparsed_scope_data_.
void SavePreParsedScopeDataForDeclarationScope();
void set_produced_preparsed_scope_data(
ProducedPreParsedScopeData* produced_preparsed_scope_data) {
produced_preparsed_scope_data_ = produced_preparsed_scope_data;
void set_preparsed_scope_data_builder(
PreParsedScopeDataBuilder* preparsed_scope_data_builder) {
preparsed_scope_data_builder_ = preparsed_scope_data_builder;
}
ProducedPreParsedScopeData* produced_preparsed_scope_data() const {
return produced_preparsed_scope_data_;
PreParsedScopeDataBuilder* preparsed_scope_data_builder() const {
return preparsed_scope_data_builder_;
}
private:
......@@ -981,7 +980,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
Variable* arguments_;
// For producing the scope allocation data during preparsing.
ProducedPreParsedScopeData* produced_preparsed_scope_data_;
PreParsedScopeDataBuilder* preparsed_scope_data_builder_;
struct RareData : public ZoneObject {
// Convenience variable; Subclass constructor only
......
......@@ -33,7 +33,7 @@ struct PreParsedScopeByteDataConstants {
4 * kUint32Size + 1 * kUint8Size;
};
class ProducedPreParsedScopeData::ByteData
class PreParsedScopeDataBuilder::ByteData
: public ZoneObject,
public PreParsedScopeByteDataConstants {
public:
......
......@@ -35,7 +35,7 @@ STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
/*
Internal data format for the backing store of ProducedPreparsedScopeData and
Internal data format for the backing store of PreParsedScopeDataBuilder and
PreParsedScopeData::scope_data (on the heap):
(Skippable function data:)
......@@ -78,7 +78,7 @@ STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
*/
void ProducedPreParsedScopeData::ByteData::WriteUint32(uint32_t data) {
void PreParsedScopeDataBuilder::ByteData::WriteUint32(uint32_t data) {
#ifdef DEBUG
// Save expected item size in debug mode.
backing_store_.push_back(kUint32Size);
......@@ -91,7 +91,7 @@ void ProducedPreParsedScopeData::ByteData::WriteUint32(uint32_t data) {
}
#ifdef DEBUG
void ProducedPreParsedScopeData::ByteData::OverwriteFirstUint32(uint32_t data) {
void PreParsedScopeDataBuilder::ByteData::OverwriteFirstUint32(uint32_t data) {
auto it = backing_store_.begin();
// Check that that position already holds an item of the expected size.
DCHECK_GE(backing_store_.size(), kUint32Size);
......@@ -104,7 +104,7 @@ void ProducedPreParsedScopeData::ByteData::OverwriteFirstUint32(uint32_t data) {
}
#endif
void ProducedPreParsedScopeData::ByteData::WriteUint8(uint8_t data) {
void PreParsedScopeDataBuilder::ByteData::WriteUint8(uint8_t data) {
#ifdef DEBUG
// Save expected item size in debug mode.
backing_store_.push_back(kUint8Size);
......@@ -113,7 +113,7 @@ void ProducedPreParsedScopeData::ByteData::WriteUint8(uint8_t data) {
free_quarters_in_last_byte_ = 0;
}
void ProducedPreParsedScopeData::ByteData::WriteQuarter(uint8_t data) {
void PreParsedScopeDataBuilder::ByteData::WriteQuarter(uint8_t data) {
DCHECK_LE(data, 3);
if (free_quarters_in_last_byte_ == 0) {
#ifdef DEBUG
......@@ -131,7 +131,7 @@ void ProducedPreParsedScopeData::ByteData::WriteQuarter(uint8_t data) {
backing_store_.back() |= (data << shift_amount);
}
Handle<PodArray<uint8_t>> ProducedPreParsedScopeData::ByteData::Serialize(
Handle<PodArray<uint8_t>> PreParsedScopeDataBuilder::ByteData::Serialize(
Isolate* isolate) {
Handle<PodArray<uint8_t>> array = PodArray<uint8_t>::New(
isolate, static_cast<int>(backing_store_.size()), TENURED);
......@@ -146,13 +146,13 @@ Handle<PodArray<uint8_t>> ProducedPreParsedScopeData::ByteData::Serialize(
return array;
}
ProducedPreParsedScopeData::ProducedPreParsedScopeData(
Zone* zone, ProducedPreParsedScopeData* parent)
PreParsedScopeDataBuilder::PreParsedScopeDataBuilder(
Zone* zone, PreParsedScopeDataBuilder* parent)
: parent_(parent),
byte_data_(new (zone) ByteData(zone)),
data_for_inner_functions_(zone),
bailed_out_(false),
previously_produced_zone_preparsed_scope_data_(nullptr) {
bailed_out_(false) {
DCHECK(FLAG_preparser_scope_analysis);
if (parent != nullptr) {
parent->data_for_inner_functions_.push_back(this);
}
......@@ -162,71 +162,43 @@ ProducedPreParsedScopeData::ProducedPreParsedScopeData(
#endif
}
// Create a ProducedPreParsedScopeData which is just a proxy for a previous
// produced PreParsedScopeData.
ProducedPreParsedScopeData::ProducedPreParsedScopeData(
Handle<PreParsedScopeData> data, Zone* zone)
: parent_(nullptr),
byte_data_(nullptr),
data_for_inner_functions_(zone),
bailed_out_(false),
previously_produced_on_heap_preparsed_scope_data_(data),
previously_produced_zone_preparsed_scope_data_(nullptr) {}
// Create a ProducedPreParsedScopeData which is just a proxy for a previous
// produced PreParsedScopeData.
ProducedPreParsedScopeData::ProducedPreParsedScopeData(
ZonePreParsedScopeData* data, Zone* zone)
: parent_(nullptr),
byte_data_(nullptr),
data_for_inner_functions_(zone),
bailed_out_(false),
previously_produced_zone_preparsed_scope_data_(data) {}
ProducedPreParsedScopeData::DataGatheringScope::DataGatheringScope(
PreParsedScopeDataBuilder::DataGatheringScope::DataGatheringScope(
DeclarationScope* function_scope, PreParser* preparser)
: function_scope_(function_scope),
preparser_(preparser),
produced_preparsed_scope_data_(nullptr) {
builder_(nullptr) {
if (FLAG_preparser_scope_analysis) {
ProducedPreParsedScopeData* parent =
preparser->produced_preparsed_scope_data();
PreParsedScopeDataBuilder* parent =
preparser->preparsed_scope_data_builder();
Zone* main_zone = preparser->main_zone();
produced_preparsed_scope_data_ =
new (main_zone) ProducedPreParsedScopeData(main_zone, parent);
preparser->set_produced_preparsed_scope_data(
produced_preparsed_scope_data_);
function_scope->set_produced_preparsed_scope_data(
produced_preparsed_scope_data_);
builder_ = new (main_zone) PreParsedScopeDataBuilder(main_zone, parent);
preparser->set_preparsed_scope_data_builder(builder_);
function_scope->set_preparsed_scope_data_builder(builder_);
}
}
ProducedPreParsedScopeData::DataGatheringScope::~DataGatheringScope() {
if (FLAG_preparser_scope_analysis) {
preparser_->set_produced_preparsed_scope_data(
produced_preparsed_scope_data_->parent_);
PreParsedScopeDataBuilder::DataGatheringScope::~DataGatheringScope() {
if (builder_) {
preparser_->set_preparsed_scope_data_builder(builder_->parent_);
}
}
void ProducedPreParsedScopeData::DataGatheringScope::MarkFunctionAsSkippable(
void PreParsedScopeDataBuilder::DataGatheringScope::MarkFunctionAsSkippable(
int end_position, int num_inner_functions) {
DCHECK(FLAG_preparser_scope_analysis);
DCHECK_NOT_NULL(produced_preparsed_scope_data_);
DCHECK_NOT_NULL(produced_preparsed_scope_data_->parent_);
produced_preparsed_scope_data_->parent_->AddSkippableFunction(
DCHECK_NOT_NULL(builder_);
DCHECK_NOT_NULL(builder_->parent_);
builder_->parent_->AddSkippableFunction(
function_scope_->start_position(), end_position,
function_scope_->num_parameters(), num_inner_functions,
function_scope_->language_mode(), function_scope_->NeedsHomeObject());
}
void ProducedPreParsedScopeData::AddSkippableFunction(
int start_position, int end_position, int num_parameters,
int num_inner_functions, LanguageMode language_mode,
void PreParsedScopeDataBuilder::AddSkippableFunction(int start_position,
int end_position,
int num_parameters,
int num_inner_functions,
LanguageMode language_mode,
bool uses_super_property) {
DCHECK(FLAG_preparser_scope_analysis);
DCHECK(previously_produced_on_heap_preparsed_scope_data_.is_null());
DCHECK_NULL(previously_produced_zone_preparsed_scope_data_);
if (bailed_out_) {
return;
}
......@@ -245,11 +217,8 @@ void ProducedPreParsedScopeData::AddSkippableFunction(
byte_data_->WriteQuarter(language_and_super);
}
void ProducedPreParsedScopeData::SaveScopeAllocationData(
void PreParsedScopeDataBuilder::SaveScopeAllocationData(
DeclarationScope* scope) {
DCHECK(FLAG_preparser_scope_analysis);
DCHECK(previously_produced_on_heap_preparsed_scope_data_.is_null());
DCHECK_NULL(previously_produced_zone_preparsed_scope_data_);
// The data contains a uint32 (reserved space for scope_data_start) and
// function data items, kSkippableFunctionDataSize each.
DCHECK_GE(byte_data_->size(), ByteData::kPlaceholderSize);
......@@ -281,24 +250,12 @@ void ProducedPreParsedScopeData::SaveScopeAllocationData(
SaveDataForScope(scope);
}
bool ProducedPreParsedScopeData::ContainsInnerFunctions() const {
bool PreParsedScopeDataBuilder::ContainsInnerFunctions() const {
return byte_data_->size() > ByteData::kPlaceholderSize;
}
MaybeHandle<PreParsedScopeData> ProducedPreParsedScopeData::Serialize(
MaybeHandle<PreParsedScopeData> PreParsedScopeDataBuilder::Serialize(
Isolate* isolate) {
if (!previously_produced_on_heap_preparsed_scope_data_.is_null()) {
DCHECK(!bailed_out_);
DCHECK_EQ(data_for_inner_functions_.size(), 0);
return previously_produced_on_heap_preparsed_scope_data_;
} else if (previously_produced_zone_preparsed_scope_data_ != nullptr) {
DCHECK(!bailed_out_);
DCHECK_EQ(data_for_inner_functions_.size(), 0);
previously_produced_on_heap_preparsed_scope_data_ =
previously_produced_zone_preparsed_scope_data_->Serialize(isolate);
return previously_produced_on_heap_preparsed_scope_data_;
}
if (bailed_out_) {
return MaybeHandle<PreParsedScopeData>();
}
......@@ -331,15 +288,7 @@ MaybeHandle<PreParsedScopeData> ProducedPreParsedScopeData::Serialize(
return data;
}
ZonePreParsedScopeData* ProducedPreParsedScopeData::Serialize(Zone* zone) {
DCHECK(previously_produced_on_heap_preparsed_scope_data_.is_null());
if (previously_produced_zone_preparsed_scope_data_ != nullptr) {
DCHECK(!bailed_out_);
DCHECK_EQ(data_for_inner_functions_.size(), 0);
return previously_produced_zone_preparsed_scope_data_;
}
ZonePreParsedScopeData* PreParsedScopeDataBuilder::Serialize(Zone* zone) {
if (bailed_out_) {
return nullptr;
}
......@@ -365,7 +314,7 @@ ZonePreParsedScopeData* ProducedPreParsedScopeData::Serialize(Zone* zone) {
return result;
}
bool ProducedPreParsedScopeData::ScopeNeedsData(Scope* scope) {
bool PreParsedScopeDataBuilder::ScopeNeedsData(Scope* scope) {
if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
// Default constructors don't need data (they cannot contain inner functions
// defined by the user). Other functions do.
......@@ -387,9 +336,9 @@ bool ProducedPreParsedScopeData::ScopeNeedsData(Scope* scope) {
return false;
}
bool ProducedPreParsedScopeData::ScopeIsSkippableFunctionScope(Scope* scope) {
bool PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(Scope* scope) {
// Lazy non-arrow function scopes are skippable. Lazy functions are exactly
// those Scopes which have their own ProducedPreParsedScopeData object. This
// those Scopes which have their own PreParsedScopeDataBuilder object. This
// logic ensures that the scope allocation data is consistent with the
// skippable function data (both agree on where the lazy function boundaries
// are).
......@@ -398,10 +347,10 @@ bool ProducedPreParsedScopeData::ScopeIsSkippableFunctionScope(Scope* scope) {
}
DeclarationScope* declaration_scope = scope->AsDeclarationScope();
return !declaration_scope->is_arrow_scope() &&
declaration_scope->produced_preparsed_scope_data() != nullptr;
declaration_scope->preparsed_scope_data_builder() != nullptr;
}
void ProducedPreParsedScopeData::SaveDataForScope(Scope* scope) {
void PreParsedScopeDataBuilder::SaveDataForScope(Scope* scope) {
DCHECK_NE(scope->end_position(), kNoSourcePosition);
if (!ScopeNeedsData(scope)) {
......@@ -435,7 +384,7 @@ void ProducedPreParsedScopeData::SaveDataForScope(Scope* scope) {
SaveDataForInnerScopes(scope);
}
void ProducedPreParsedScopeData::SaveDataForVariable(Variable* var) {
void PreParsedScopeDataBuilder::SaveDataForVariable(Variable* var) {
#ifdef DEBUG
// Store the variable name in debug mode; this way we can check that we
// restore data to the correct variable.
......@@ -453,7 +402,7 @@ void ProducedPreParsedScopeData::SaveDataForVariable(Variable* var) {
byte_data_->WriteQuarter(variable_data);
}
void ProducedPreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
void PreParsedScopeDataBuilder::SaveDataForInnerScopes(Scope* scope) {
// Inner scopes are stored in the reverse order, but we'd like to write the
// data in the logical order. There might be many inner scopes, so we don't
// want to recurse here.
......@@ -462,9 +411,9 @@ void ProducedPreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
inner = inner->sibling()) {
if (ScopeIsSkippableFunctionScope(inner)) {
// Don't save data about function scopes, since they'll have their own
// ProducedPreParsedScopeData where their data is saved.
// PreParsedScopeDataBuilder where their data is saved.
DCHECK_NOT_NULL(
inner->AsDeclarationScope()->produced_preparsed_scope_data());
inner->AsDeclarationScope()->preparsed_scope_data_builder());
continue;
}
scopes.push_back(inner);
......@@ -474,6 +423,73 @@ void ProducedPreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
}
}
class BuilderProducedPreParsedScopeData final
: public ProducedPreParsedScopeData {
public:
explicit BuilderProducedPreParsedScopeData(PreParsedScopeDataBuilder* builder)
: builder_(builder) {}
MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate) final {
return builder_->Serialize(isolate);
}
ZonePreParsedScopeData* Serialize(Zone* zone) final {
return builder_->Serialize(zone);
};
private:
PreParsedScopeDataBuilder* builder_;
};
class OnHeapProducedPreParsedScopeData final
: public ProducedPreParsedScopeData {
public:
explicit OnHeapProducedPreParsedScopeData(Handle<PreParsedScopeData> data)
: data_(data) {}
MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate) final {
return data_;
}
ZonePreParsedScopeData* Serialize(Zone* zone) final {
// Not required.
UNREACHABLE();
};
private:
Handle<PreParsedScopeData> data_;
};
class ZoneProducedPreParsedScopeData final : public ProducedPreParsedScopeData {
public:
explicit ZoneProducedPreParsedScopeData(ZonePreParsedScopeData* data)
: data_(data) {}
MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate) final {
return data_->Serialize(isolate);
}
ZonePreParsedScopeData* Serialize(Zone* zone) final { return data_; };
private:
ZonePreParsedScopeData* data_;
};
ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
PreParsedScopeDataBuilder* builder, Zone* zone) {
return new (zone) BuilderProducedPreParsedScopeData(builder);
}
ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
Handle<PreParsedScopeData> data, Zone* zone) {
return new (zone) OnHeapProducedPreParsedScopeData(data);
}
ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
ZonePreParsedScopeData* data, Zone* zone) {
return new (zone) ZoneProducedPreParsedScopeData(data);
}
template <class Data>
ProducedPreParsedScopeData*
BaseConsumedPreParsedScopeData<Data>::GetDataForSkippableFunction(
......@@ -505,7 +521,6 @@ BaseConsumedPreParsedScopeData<Data>::GetDataForSkippableFunction(
template <class Data>
void BaseConsumedPreParsedScopeData<Data>::RestoreScopeAllocationData(
DeclarationScope* scope) {
DCHECK(FLAG_preparser_scope_analysis);
DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
typename ByteData::ReadingScope reading_scope(this);
......@@ -536,7 +551,7 @@ void BaseConsumedPreParsedScopeData<Data>::RestoreData(Scope* scope) {
// It's possible that scope is not present in the data at all (since PreParser
// doesn't create the corresponding scope). In this case, the Scope won't
// contain any variables for which we need the data.
if (!ProducedPreParsedScopeData::ScopeNeedsData(scope)) {
if (!PreParsedScopeDataBuilder::ScopeNeedsData(scope)) {
return;
}
......@@ -642,7 +657,7 @@ ProducedPreParsedScopeData* OnHeapConsumedPreParsedScopeData::GetChildData(
}
Handle<PreParsedScopeData> child_data_handle(
PreParsedScopeData::cast(child_data), isolate_);
return new (zone) ProducedPreParsedScopeData(child_data_handle, zone);
return ProducedPreParsedScopeData::For(child_data_handle, zone);
}
OnHeapConsumedPreParsedScopeData::OnHeapConsumedPreParsedScopeData(
......@@ -703,7 +718,7 @@ ProducedPreParsedScopeData* ZoneConsumedPreParsedScopeData::GetChildData(
if (child_data == nullptr) {
return nullptr;
}
return new (zone) ProducedPreParsedScopeData(child_data, zone);
return ProducedPreParsedScopeData::For(child_data, zone);
}
std::unique_ptr<ConsumedPreParsedScopeData> ConsumedPreParsedScopeData::For(
......
......@@ -62,23 +62,15 @@ class ZonePreParsedScopeData;
*/
class ProducedPreParsedScopeData : public ZoneObject {
class PreParsedScopeDataBuilder : public ZoneObject {
public:
class ByteData;
// Create a ProducedPreParsedScopeData object which will collect data as we
// Create a PreParsedScopeDataBuilder object which will collect data as we
// parse.
ProducedPreParsedScopeData(Zone* zone, ProducedPreParsedScopeData* parent);
// Create a ProducedPreParsedScopeData which is just a proxy for a previous
// produced PreParsedScopeData on the heap.
ProducedPreParsedScopeData(Handle<PreParsedScopeData> data, Zone* zone);
// Create a ProducedPreParsedScopeData which is just a proxy for a previous
// produced PreParsedScopeData in zone.
ProducedPreParsedScopeData(ZonePreParsedScopeData* data, Zone* zone);
PreParsedScopeDataBuilder(Zone* zone, PreParsedScopeDataBuilder* parent);
ProducedPreParsedScopeData* parent() const { return parent_; }
PreParsedScopeDataBuilder* parent() const { return parent_; }
// For gathering the inner function data and splitting it up according to the
// laziness boundaries. Each lazy function gets its own
......@@ -93,7 +85,7 @@ class ProducedPreParsedScopeData : public ZoneObject {
private:
DeclarationScope* function_scope_;
PreParser* preparser_;
ProducedPreParsedScopeData* produced_preparsed_scope_data_;
PreParsedScopeDataBuilder* builder_;
DISALLOW_COPY_AND_ASSIGN(DataGatheringScope);
};
......@@ -129,20 +121,15 @@ class ProducedPreParsedScopeData : public ZoneObject {
bool ContainsInnerFunctions() const;
// If there is data (if the Scope contains skippable inner functions), move
// the data into the heap and return a Handle to it; otherwise return a null
// MaybeHandle.
MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate);
// If there is data (if the Scope contains skippable inner functions), return
// an off-heap ZonePreParsedScopeData representing the data; otherwise
// return nullptr.
ZonePreParsedScopeData* Serialize(Zone* zone);
static bool ScopeNeedsData(Scope* scope);
static bool ScopeIsSkippableFunctionScope(Scope* scope);
private:
friend class BuilderProducedPreParsedScopeData;
virtual MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate);
virtual ZonePreParsedScopeData* Serialize(Zone* zone);
void AddSkippableFunction(int start_position, int end_position,
int num_parameters, int num_inner_functions,
LanguageMode language_mode,
......@@ -152,27 +139,43 @@ class ProducedPreParsedScopeData : public ZoneObject {
void SaveDataForVariable(Variable* var);
void SaveDataForInnerScopes(Scope* scope);
ProducedPreParsedScopeData* parent_;
PreParsedScopeDataBuilder* parent_;
ByteData* byte_data_;
ZoneChunkList<ProducedPreParsedScopeData*> data_for_inner_functions_;
ZoneChunkList<PreParsedScopeDataBuilder*> data_for_inner_functions_;
// Whether we've given up producing the data for this function.
bool bailed_out_;
// ProducedPreParsedScopeData can also hold a Handle<PreParsedScopeData>
// which was produced already earlier. This happens for deeper lazy functions.
// TODO(rmcilroy): Split apart ProducedPreParsedScopeData into different
// classes for situations where it has already been produced.
Handle<PreParsedScopeData> previously_produced_on_heap_preparsed_scope_data_;
DISALLOW_COPY_AND_ASSIGN(PreParsedScopeDataBuilder);
};
// ProducedPreParsedScopeData can also hold a ZonePreParsedScopeData*
// which was produced already earlier. This happens for deeper lazy functions.
// TODO(rmcilroy): Split apart ProducedPreParsedScopeData into different
// classes for situations where it has already been produced.
ZonePreParsedScopeData* previously_produced_zone_preparsed_scope_data_;
class ProducedPreParsedScopeData : public ZoneObject {
public:
// If there is data (if the Scope contains skippable inner functions), move
// the data into the heap and return a Handle to it; otherwise return a null
// MaybeHandle.
virtual MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate) = 0;
DISALLOW_COPY_AND_ASSIGN(ProducedPreParsedScopeData);
// If there is data (if the Scope contains skippable inner functions), return
// an off-heap ZonePreParsedScopeData representing the data; otherwise
// return nullptr.
virtual ZonePreParsedScopeData* Serialize(Zone* zone) = 0;
// Create a ProducedPreParsedScopeData which is a proxy for a previous
// produced PreParsedScopeData in zone.
static ProducedPreParsedScopeData* For(PreParsedScopeDataBuilder* builder,
Zone* zone);
// Create a ProducedPreParsedScopeData which is a proxy for a previous
// produced PreParsedScopeData on the heap.
static ProducedPreParsedScopeData* For(Handle<PreParsedScopeData> data,
Zone* zone);
// Create a ProducedPreParsedScopeData which is a proxy for a previous
// produced PreParsedScopeData in zone.
static ProducedPreParsedScopeData* For(ZonePreParsedScopeData* data,
Zone* zone);
};
class ConsumedPreParsedScopeData {
......
......@@ -134,12 +134,12 @@ PreParser::PreParseResult PreParser::PreParseFunction(
// Start collecting data for a new function which might contain skippable
// functions.
std::unique_ptr<ProducedPreParsedScopeData::DataGatheringScope>
produced_preparsed_scope_data_scope;
std::unique_ptr<PreParsedScopeDataBuilder::DataGatheringScope>
preparsed_scope_data_builder_scope;
if (FLAG_preparser_scope_analysis && !IsArrowFunction(kind)) {
DCHECK(track_unresolved_variables_);
produced_preparsed_scope_data_scope.reset(
new ProducedPreParsedScopeData::DataGatheringScope(function_scope,
preparsed_scope_data_builder_scope.reset(
new PreParsedScopeDataBuilder::DataGatheringScope(function_scope,
this));
}
......@@ -239,7 +239,8 @@ PreParser::PreParseResult PreParser::PreParseFunction(
allow_duplicate_parameters,
CHECK_OK_VALUE(kPreParseSuccess));
*produced_preparsed_scope_data = produced_preparsed_scope_data_;
*produced_preparsed_scope_data = ProducedPreParsedScopeData::For(
preparsed_scope_data_builder_, main_zone());
}
if (is_strict(function_scope->language_mode())) {
......@@ -292,14 +293,14 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
// Start collecting data for a new function which might contain skippable
// functions.
std::unique_ptr<ProducedPreParsedScopeData::DataGatheringScope>
produced_preparsed_scope_data_scope;
std::unique_ptr<PreParsedScopeDataBuilder::DataGatheringScope>
preparsed_scope_data_builder_scope;
if (!function_state_->next_function_is_likely_called() &&
produced_preparsed_scope_data_ != nullptr) {
preparsed_scope_data_builder_ != nullptr) {
DCHECK(FLAG_preparser_scope_analysis);
DCHECK(track_unresolved_variables_);
produced_preparsed_scope_data_scope.reset(
new ProducedPreParsedScopeData::DataGatheringScope(function_scope,
preparsed_scope_data_builder_scope.reset(
new PreParsedScopeDataBuilder::DataGatheringScope(function_scope,
this));
}
......@@ -348,8 +349,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
}
if (produced_preparsed_scope_data_scope) {
produced_preparsed_scope_data_scope->MarkFunctionAsSkippable(
if (preparsed_scope_data_builder_scope) {
preparsed_scope_data_builder_scope->MarkFunctionAsSkippable(
end_position, GetLastFunctionLiteralId() - func_id);
}
if (V8_UNLIKELY(FLAG_log_function_events)) {
......@@ -396,19 +397,19 @@ PreParserStatement PreParser::BuildParameterInitializationBlock(
DCHECK(scope()->is_function_scope());
if (FLAG_preparser_scope_analysis &&
scope()->AsDeclarationScope()->calls_sloppy_eval() &&
produced_preparsed_scope_data_ != nullptr) {
preparsed_scope_data_builder_ != nullptr) {
// We cannot replicate the Scope structure constructed by the Parser,
// because we've lost information whether each individual parameter was
// simple or not. Give up trying to produce data to skip inner functions.
if (produced_preparsed_scope_data_->parent() != nullptr) {
if (preparsed_scope_data_builder_->parent() != nullptr) {
// Lazy parsing started before the current function; the function which
// cannot contain skippable functions is the parent function. (Its inner
// functions cannot either; they are implicitly bailed out.)
produced_preparsed_scope_data_->parent()->Bailout();
preparsed_scope_data_builder_->parent()->Bailout();
} else {
// Lazy parsing started at the current function; it cannot contain
// skippable functions.
produced_preparsed_scope_data_->Bailout();
preparsed_scope_data_builder_->Bailout();
}
}
......
......@@ -22,7 +22,7 @@ namespace internal {
// interface as AstNodeFactory, so ParserBase doesn't need to care which one is
// used.
class ProducedPreParsedScopeData;
class PreParsedScopeDataBuilder;
class PreParserIdentifier {
public:
......@@ -958,7 +958,7 @@ class PreParser : public ParserBase<PreParser> {
parsing_module, parsing_on_main_thread),
use_counts_(nullptr),
track_unresolved_variables_(false),
produced_preparsed_scope_data_(nullptr) {}
preparsed_scope_data_builder_(nullptr) {}
static bool IsPreParser() { return true; }
......@@ -990,13 +990,13 @@ class PreParser : public ParserBase<PreParser> {
return FLAG_preparser_scope_analysis || is_inner_function;
}
ProducedPreParsedScopeData* produced_preparsed_scope_data() const {
return produced_preparsed_scope_data_;
PreParsedScopeDataBuilder* preparsed_scope_data_builder() const {
return preparsed_scope_data_builder_;
}
void set_produced_preparsed_scope_data(
ProducedPreParsedScopeData* produced_preparsed_scope_data) {
produced_preparsed_scope_data_ = produced_preparsed_scope_data;
void set_preparsed_scope_data_builder(
PreParsedScopeDataBuilder* preparsed_scope_data_builder) {
preparsed_scope_data_builder_ = preparsed_scope_data_builder;
}
private:
......@@ -1769,7 +1769,7 @@ class PreParser : public ParserBase<PreParser> {
bool track_unresolved_variables_;
PreParserLogger log_;
ProducedPreParsedScopeData* produced_preparsed_scope_data_;
PreParsedScopeDataBuilder* preparsed_scope_data_builder_;
};
PreParserExpression PreParser::SpreadCall(const PreParserExpression& function,
......
......@@ -815,7 +815,7 @@ TEST(ProducingAndConsumingByteData) {
LocalContext env;
i::Zone zone(isolate->allocator(), ZONE_NAME);
i::ProducedPreParsedScopeData::ByteData bytes(&zone);
i::PreParsedScopeDataBuilder::ByteData bytes(&zone);
// Write some data.
bytes.WriteUint32(1983); // This will be overwritten.
bytes.WriteUint32(2147483647);
......
......@@ -24,7 +24,7 @@ class ScopeTestHelper {
baseline->AsDeclarationScope()->function_kind() ==
scope->AsDeclarationScope()->function_kind());
if (!ProducedPreParsedScopeData::ScopeNeedsData(baseline)) {
if (!PreParsedScopeDataBuilder::ScopeNeedsData(baseline)) {
return;
}
......
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