Commit a17f2446 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[parser] Skipping inner funcs: Distinguish between skippable and non-skippable functions.

We collect function data for 2 purposes:
- Variable allocation data for lazy parsed functions which contain skippable functions.
- Data needed for creating FunctionLiterals for skippable functions.

In some cases, recompilation happens, and we need to make sure we're not trying
to skip a non-skippable function.

At the moment, we don't collect data for eagerly parsed scopes, since the
assumption is that they'll never get recompiled. (Fixing that will bigger design
changes.)

After this, we're down to 2 failures for mjsunit + --experimental-preparser-scope-analysis.


BUG=v8:5516

Change-Id: I704d488269f6d20a4b14596f2a0acc342ede32cb
Reviewed-on: https://chromium-review.googlesource.com/486802
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarDaniel Vogelheim <vogelheim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44848}
parent 9685cfd3
...@@ -2863,7 +2863,8 @@ Parser::LazyParsingResult Parser::SkipFunction(FunctionKind kind, ...@@ -2863,7 +2863,8 @@ Parser::LazyParsingResult Parser::SkipFunction(FunctionKind kind,
if (preparsed_scope_data_->Consuming()) { if (preparsed_scope_data_->Consuming()) {
DCHECK(FLAG_experimental_preparser_scope_analysis); DCHECK(FLAG_experimental_preparser_scope_analysis);
const PreParseData::FunctionData& data = const PreParseData::FunctionData& data =
preparsed_scope_data_->FindFunction(function_scope->start_position()); preparsed_scope_data_->FindSkippableFunction(
function_scope->start_position());
if (data.is_valid()) { if (data.is_valid()) {
function_scope->set_is_skipped_function(true); function_scope->set_is_skipped_function(true);
function_scope->outer_scope()->SetMustUsePreParsedScopeData(); function_scope->outer_scope()->SetMustUsePreParsedScopeData();
......
...@@ -20,7 +20,7 @@ class VariableMaybeAssignedField ...@@ -20,7 +20,7 @@ class VariableMaybeAssignedField
class VariableContextAllocatedField class VariableContextAllocatedField
: public BitField16<bool, VariableMaybeAssignedField::kNext, 1> {}; : public BitField16<bool, VariableMaybeAssignedField::kNext, 1> {};
const int kFunctionDataSize = 7; const int kFunctionDataSize = 8;
} // namespace } // namespace
...@@ -88,6 +88,12 @@ void PreParsedScopeData::SaveData(Scope* scope) { ...@@ -88,6 +88,12 @@ void PreParsedScopeData::SaveData(Scope* scope) {
backing_store_[data_end_index] = static_cast<uint32_t>(backing_store_.size()); backing_store_[data_end_index] = static_cast<uint32_t>(backing_store_.size());
} }
void PreParsedScopeData::AddSkippableFunction(
int start_position, const PreParseData::FunctionData& function_data) {
AddFunction(start_position, function_data);
skippable_functions_.insert(start_position);
}
void PreParsedScopeData::AddFunction( void PreParsedScopeData::AddFunction(
int start_position, const PreParseData::FunctionData& function_data) { int start_position, const PreParseData::FunctionData& function_data) {
function_index_.AddFunctionData(start_position, function_data); function_index_.AddFunctionData(start_position, function_data);
...@@ -120,7 +126,7 @@ void PreParsedScopeData::RestoreData(Scope* scope, uint32_t* index_ptr) const { ...@@ -120,7 +126,7 @@ void PreParsedScopeData::RestoreData(Scope* scope, uint32_t* index_ptr) const {
if (scope->scope_type() == ScopeType::FUNCTION_SCOPE && if (scope->scope_type() == ScopeType::FUNCTION_SCOPE &&
!scope->AsDeclarationScope()->is_arrow_scope()) { !scope->AsDeclarationScope()->is_arrow_scope()) {
const PreParseData::FunctionData& data = const PreParseData::FunctionData& data =
FindFunction(scope->start_position()); function_index_.GetFunctionData(scope->start_position());
DCHECK_EQ(data.end, scope->end_position()); DCHECK_EQ(data.end, scope->end_position());
// FIXME(marja): unify num_parameters too and DCHECK here. // FIXME(marja): unify num_parameters too and DCHECK here.
DCHECK_EQ(data.language_mode, scope->language_mode()); DCHECK_EQ(data.language_mode, scope->language_mode());
...@@ -185,11 +191,14 @@ Handle<PodArray<uint32_t>> PreParsedScopeData::Serialize( ...@@ -185,11 +191,14 @@ Handle<PodArray<uint32_t>> PreParsedScopeData::Serialize(
array->set(i++, function_data.num_inner_functions); array->set(i++, function_data.num_inner_functions);
array->set(i++, function_data.language_mode); array->set(i++, function_data.language_mode);
array->set(i++, function_data.uses_super_property); array->set(i++, function_data.uses_super_property);
array->set(i++, skippable_functions_.find(item.first) !=
skippable_functions_.end());
} }
for (size_t j = 0; j < backing_store_.size(); ++j) { for (size_t j = 0; j < backing_store_.size(); ++j) {
array->set(i++, static_cast<uint32_t>(backing_store_[j])); array->set(i++, static_cast<uint32_t>(backing_store_[j]));
} }
DCHECK_EQ(array->length(), length);
return array; return array;
} }
...@@ -212,6 +221,9 @@ void PreParsedScopeData::Deserialize(PodArray<uint32_t>* array) { ...@@ -212,6 +221,9 @@ void PreParsedScopeData::Deserialize(PodArray<uint32_t>* array) {
start, PreParseData::FunctionData( start, PreParseData::FunctionData(
array->get(i + 2), array->get(i + 3), array->get(i + 4), array->get(i + 2), array->get(i + 3), array->get(i + 4),
LanguageMode(array->get(i + 5)), array->get(i + 6))); LanguageMode(array->get(i + 5)), array->get(i + 6)));
if (array->get(i + 7)) {
skippable_functions_.insert(start);
}
} }
CHECK_EQ(function_index_.size(), function_count); CHECK_EQ(function_index_.size(), function_count);
...@@ -221,8 +233,11 @@ void PreParsedScopeData::Deserialize(PodArray<uint32_t>* array) { ...@@ -221,8 +233,11 @@ void PreParsedScopeData::Deserialize(PodArray<uint32_t>* array) {
} }
} }
PreParseData::FunctionData PreParsedScopeData::FindFunction( PreParseData::FunctionData PreParsedScopeData::FindSkippableFunction(
int start_pos) const { int start_pos) const {
if (skippable_functions_.find(start_pos) == skippable_functions_.end()) {
return PreParseData::FunctionData();
}
return function_index_.GetFunctionData(start_pos); return function_index_.GetFunctionData(start_pos);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef V8_PARSING_PREPARSED_SCOPE_DATA_H_ #ifndef V8_PARSING_PREPARSED_SCOPE_DATA_H_
#define V8_PARSING_PREPARSED_SCOPE_DATA_H_ #define V8_PARSING_PREPARSED_SCOPE_DATA_H_
#include <set>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
...@@ -65,8 +66,15 @@ class PreParsedScopeData { ...@@ -65,8 +66,15 @@ class PreParsedScopeData {
// subscopes') variables. // subscopes') variables.
void SaveData(Scope* scope); void SaveData(Scope* scope);
// Saves data for a function that can be later skipped, or a function for // Save data for a function we might skip later. The data is used later for
// which we save variable allocation data. // creating a FunctionLiteral.
void AddSkippableFunction(int start_position,
const PreParseData::FunctionData& function_data);
// Save variable allocation data for function which contains skippable
// functions.
void AddFunction(int start_position,
const PreParseData::FunctionData& function_data);
// FIXME(marja): We need different kinds of data for the two types of // FIXME(marja): We need different kinds of data for the two types of
// functions. For a skippable function we need the end position + the data // functions. For a skippable function we need the end position + the data
...@@ -74,8 +82,6 @@ class PreParsedScopeData { ...@@ -74,8 +82,6 @@ class PreParsedScopeData {
// skippable functions, we need the data affecting context allocation status // skippable functions, we need the data affecting context allocation status
// of the variables (but e.g., no end position). Currently we just save the // of the variables (but e.g., no end position). Currently we just save the
// same data for both. Here we can save less data. // same data for both. Here we can save less data.
void AddFunction(int start_position,
const PreParseData::FunctionData& function_data);
// Restores the information needed for allocating the Scopes's (and its // Restores the information needed for allocating the Scopes's (and its
// subscopes') variables. // subscopes') variables.
...@@ -89,7 +95,7 @@ class PreParsedScopeData { ...@@ -89,7 +95,7 @@ class PreParsedScopeData {
bool Producing() const { return !has_data_; } bool Producing() const { return !has_data_; }
PreParseData::FunctionData FindFunction(int start_pos) const; PreParseData::FunctionData FindSkippableFunction(int start_pos) const;
private: private:
friend class ScopeTestHelper; friend class ScopeTestHelper;
...@@ -112,6 +118,8 @@ class PreParsedScopeData { ...@@ -112,6 +118,8 @@ class PreParsedScopeData {
PreParseData function_index_; PreParseData function_index_;
// Start pos -> position in backing_store_. // Start pos -> position in backing_store_.
std::unordered_map<uint32_t, uint32_t> function_data_positions_; std::unordered_map<uint32_t, uint32_t> function_data_positions_;
// Start positions of skippable functions.
std::set<uint32_t> skippable_functions_;
bool has_data_ = false; bool has_data_ = false;
......
...@@ -217,6 +217,8 @@ PreParser::PreParseResult PreParser::PreParseFunction( ...@@ -217,6 +217,8 @@ PreParser::PreParseResult PreParser::PreParseFunction(
if (FLAG_experimental_preparser_scope_analysis && if (FLAG_experimental_preparser_scope_analysis &&
preparsed_scope_data_ != nullptr) { preparsed_scope_data_ != nullptr) {
// We're not going to skip this function, but it might contain skippable
// functions inside it.
preparsed_scope_data_->AddFunction( preparsed_scope_data_->AddFunction(
scope()->start_position(), scope()->start_position(),
PreParseData::FunctionData( PreParseData::FunctionData(
...@@ -355,7 +357,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( ...@@ -355,7 +357,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
if (FLAG_experimental_preparser_scope_analysis && if (FLAG_experimental_preparser_scope_analysis &&
track_unresolved_variables_ && preparsed_scope_data_ != nullptr) { track_unresolved_variables_ && preparsed_scope_data_ != nullptr) {
preparsed_scope_data_->AddFunction( preparsed_scope_data_->AddSkippableFunction(
start_position, start_position,
PreParseData::FunctionData( PreParseData::FunctionData(
end_position, scope()->num_parameters(), end_position, scope()->num_parameters(),
......
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