Parser: store parameters in a ThreadedList instead of ZoneList.
ThreadedList is more memory-efficient than ZoneList. This also enables us to use ThreadedList when making Preparser track parameters (upcoming work). BUG=v8:5501 Review-Url: https://codereview.chromium.org/2531593002 Cr-Commit-Position: refs/heads/master@{#41307}
This commit is contained in:
parent
0f48dc7cce
commit
b31cbbd443
@ -3520,10 +3520,7 @@ void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < parameters->arity; ++i) {
|
impl()->DeclareFormalParameters(parameters->scope, parameters->params);
|
||||||
auto parameter = parameters->at(i);
|
|
||||||
impl()->DeclareFormalParameter(parameters->scope, parameter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
|
@ -964,7 +964,7 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
|
|||||||
} else {
|
} else {
|
||||||
// BindingIdentifier
|
// BindingIdentifier
|
||||||
ParseFormalParameter(&formals, &ok);
|
ParseFormalParameter(&formals, &ok);
|
||||||
if (ok) DeclareFormalParameter(formals.scope, formals.at(0));
|
if (ok) DeclareFormalParameters(formals.scope, formals.params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2476,15 +2476,11 @@ void Parser::DeclareArrowFunctionFormalParameters(
|
|||||||
if (!parameters->is_simple) {
|
if (!parameters->is_simple) {
|
||||||
this->classifier()->RecordNonSimpleParameter();
|
this->classifier()->RecordNonSimpleParameter();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < parameters->arity; ++i) {
|
DeclareFormalParameters(parameters->scope, parameters->params);
|
||||||
auto parameter = parameters->at(i);
|
if (!this->classifier()
|
||||||
DeclareFormalParameter(parameters->scope, parameter);
|
->is_valid_formal_parameter_list_without_duplicates()) {
|
||||||
if (!this->classifier()
|
*duplicate_loc =
|
||||||
->is_valid_formal_parameter_list_without_duplicates() &&
|
this->classifier()->duplicate_formal_parameter_error().location;
|
||||||
!duplicate_loc->IsValid()) {
|
|
||||||
*duplicate_loc =
|
|
||||||
this->classifier()->duplicate_formal_parameter_error().location;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
|
DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
|
||||||
}
|
}
|
||||||
@ -2493,9 +2489,9 @@ void Parser::ReindexLiterals(const ParserFormalParameters& parameters) {
|
|||||||
if (function_state_->materialized_literal_count() > 0) {
|
if (function_state_->materialized_literal_count() > 0) {
|
||||||
AstLiteralReindexer reindexer;
|
AstLiteralReindexer reindexer;
|
||||||
|
|
||||||
for (const auto p : parameters.params) {
|
for (auto p : parameters.params) {
|
||||||
if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
|
if (p->pattern != nullptr) reindexer.Reindex(p->pattern);
|
||||||
if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
|
if (p->initializer != nullptr) reindexer.Reindex(p->initializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
DCHECK(reindexer.count() <= function_state_->materialized_literal_count());
|
DCHECK(reindexer.count() <= function_state_->materialized_literal_count());
|
||||||
@ -2926,44 +2922,44 @@ Block* Parser::BuildParameterInitializationBlock(
|
|||||||
DCHECK(!parameters.is_simple);
|
DCHECK(!parameters.is_simple);
|
||||||
DCHECK(scope()->is_function_scope());
|
DCHECK(scope()->is_function_scope());
|
||||||
Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
|
Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
|
||||||
for (int i = 0; i < parameters.params.length(); ++i) {
|
int index = 0;
|
||||||
auto parameter = parameters.params[i];
|
for (auto parameter : parameters.params) {
|
||||||
if (parameter.is_rest && parameter.pattern->IsVariableProxy()) break;
|
if (parameter->is_rest && parameter->pattern->IsVariableProxy()) break;
|
||||||
DeclarationDescriptor descriptor;
|
DeclarationDescriptor descriptor;
|
||||||
descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
|
descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
|
||||||
descriptor.scope = scope();
|
descriptor.scope = scope();
|
||||||
descriptor.hoist_scope = nullptr;
|
descriptor.hoist_scope = nullptr;
|
||||||
descriptor.mode = LET;
|
descriptor.mode = LET;
|
||||||
descriptor.declaration_pos = parameter.pattern->position();
|
descriptor.declaration_pos = parameter->pattern->position();
|
||||||
// The position that will be used by the AssignmentExpression
|
// The position that will be used by the AssignmentExpression
|
||||||
// which copies from the temp parameter to the pattern.
|
// which copies from the temp parameter to the pattern.
|
||||||
//
|
//
|
||||||
// TODO(adamk): Should this be kNoSourcePosition, since
|
// TODO(adamk): Should this be kNoSourcePosition, since
|
||||||
// it's just copying from a temp var to the real param var?
|
// it's just copying from a temp var to the real param var?
|
||||||
descriptor.initialization_pos = parameter.pattern->position();
|
descriptor.initialization_pos = parameter->pattern->position();
|
||||||
Expression* initial_value =
|
Expression* initial_value =
|
||||||
factory()->NewVariableProxy(parameters.scope->parameter(i));
|
factory()->NewVariableProxy(parameters.scope->parameter(index));
|
||||||
if (parameter.initializer != nullptr) {
|
if (parameter->initializer != nullptr) {
|
||||||
// IS_UNDEFINED($param) ? initializer : $param
|
// IS_UNDEFINED($param) ? initializer : $param
|
||||||
|
|
||||||
// Ensure initializer is rewritten
|
// Ensure initializer is rewritten
|
||||||
RewriteParameterInitializer(parameter.initializer, scope());
|
RewriteParameterInitializer(parameter->initializer, scope());
|
||||||
|
|
||||||
auto condition = factory()->NewCompareOperation(
|
auto condition = factory()->NewCompareOperation(
|
||||||
Token::EQ_STRICT,
|
Token::EQ_STRICT,
|
||||||
factory()->NewVariableProxy(parameters.scope->parameter(i)),
|
factory()->NewVariableProxy(parameters.scope->parameter(index)),
|
||||||
factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
|
factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
|
||||||
initial_value = factory()->NewConditional(
|
initial_value = factory()->NewConditional(
|
||||||
condition, parameter.initializer, initial_value, kNoSourcePosition);
|
condition, parameter->initializer, initial_value, kNoSourcePosition);
|
||||||
descriptor.initialization_pos = parameter.initializer->position();
|
descriptor.initialization_pos = parameter->initializer->position();
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope* param_scope = scope();
|
Scope* param_scope = scope();
|
||||||
Block* param_block = init_block;
|
Block* param_block = init_block;
|
||||||
if (!parameter.is_simple() && scope()->calls_sloppy_eval()) {
|
if (!parameter->is_simple() && scope()->calls_sloppy_eval()) {
|
||||||
param_scope = NewVarblockScope();
|
param_scope = NewVarblockScope();
|
||||||
param_scope->set_start_position(descriptor.initialization_pos);
|
param_scope->set_start_position(descriptor.initialization_pos);
|
||||||
param_scope->set_end_position(parameter.initializer_end_position);
|
param_scope->set_end_position(parameter->initializer_end_position);
|
||||||
param_scope->RecordEvalCall();
|
param_scope->RecordEvalCall();
|
||||||
param_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition);
|
param_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition);
|
||||||
param_block->set_scope(param_scope);
|
param_block->set_scope(param_scope);
|
||||||
@ -2978,7 +2974,7 @@ Block* Parser::BuildParameterInitializationBlock(
|
|||||||
|
|
||||||
BlockState block_state(&scope_state_, param_scope);
|
BlockState block_state(&scope_state_, param_scope);
|
||||||
DeclarationParsingResult::Declaration decl(
|
DeclarationParsingResult::Declaration decl(
|
||||||
parameter.pattern, parameter.initializer_end_position, initial_value);
|
parameter->pattern, parameter->initializer_end_position, initial_value);
|
||||||
PatternRewriter::DeclareAndInitializeVariables(
|
PatternRewriter::DeclareAndInitializeVariables(
|
||||||
this, param_block, &descriptor, &decl, nullptr, CHECK_OK);
|
this, param_block, &descriptor, &decl, nullptr, CHECK_OK);
|
||||||
|
|
||||||
@ -2989,6 +2985,7 @@ Block* Parser::BuildParameterInitializationBlock(
|
|||||||
}
|
}
|
||||||
init_block->statements()->Add(param_block, zone());
|
init_block->statements()->Add(param_block, zone());
|
||||||
}
|
}
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
return init_block;
|
return init_block;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "src/parsing/preparse-data.h"
|
#include "src/parsing/preparse-data.h"
|
||||||
#include "src/parsing/preparser.h"
|
#include "src/parsing/preparser.h"
|
||||||
#include "src/pending-compilation-error-handler.h"
|
#include "src/pending-compilation-error-handler.h"
|
||||||
|
#include "src/utils.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
|
|
||||||
@ -135,7 +136,7 @@ class Parser;
|
|||||||
|
|
||||||
|
|
||||||
struct ParserFormalParameters : FormalParametersBase {
|
struct ParserFormalParameters : FormalParametersBase {
|
||||||
struct Parameter {
|
struct Parameter : public ZoneObject {
|
||||||
Parameter(const AstRawString* name, Expression* pattern,
|
Parameter(const AstRawString* name, Expression* pattern,
|
||||||
Expression* initializer, int initializer_end_position,
|
Expression* initializer, int initializer_end_position,
|
||||||
bool is_rest)
|
bool is_rest)
|
||||||
@ -149,16 +150,17 @@ struct ParserFormalParameters : FormalParametersBase {
|
|||||||
Expression* initializer;
|
Expression* initializer;
|
||||||
int initializer_end_position;
|
int initializer_end_position;
|
||||||
bool is_rest;
|
bool is_rest;
|
||||||
|
Parameter* next_parameter = nullptr;
|
||||||
bool is_simple() const {
|
bool is_simple() const {
|
||||||
return pattern->IsVariableProxy() && initializer == nullptr && !is_rest;
|
return pattern->IsVariableProxy() && initializer == nullptr && !is_rest;
|
||||||
}
|
}
|
||||||
|
Parameter** next() { return &next_parameter; }
|
||||||
|
Parameter* const* next() const { return &next_parameter; }
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ParserFormalParameters(DeclarationScope* scope)
|
explicit ParserFormalParameters(DeclarationScope* scope)
|
||||||
: FormalParametersBase(scope), params(4, scope->zone()) {}
|
: FormalParametersBase(scope) {}
|
||||||
ZoneList<Parameter> params;
|
ThreadedList<Parameter> params;
|
||||||
|
|
||||||
const Parameter& at(int i) const { return params[i]; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -1045,34 +1047,39 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
|||||||
const AstRawString* name = is_simple
|
const AstRawString* name = is_simple
|
||||||
? pattern->AsVariableProxy()->raw_name()
|
? pattern->AsVariableProxy()->raw_name()
|
||||||
: ast_value_factory()->empty_string();
|
: ast_value_factory()->empty_string();
|
||||||
parameters->params.Add(
|
auto parameter =
|
||||||
ParserFormalParameters::Parameter(name, pattern, initializer,
|
new (parameters->scope->zone()) ParserFormalParameters::Parameter(
|
||||||
initializer_end_position, is_rest),
|
name, pattern, initializer, initializer_end_position, is_rest);
|
||||||
parameters->scope->zone());
|
|
||||||
|
parameters->params.Add(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
V8_INLINE void DeclareFormalParameter(
|
V8_INLINE void DeclareFormalParameters(
|
||||||
DeclarationScope* scope,
|
DeclarationScope* scope,
|
||||||
const ParserFormalParameters::Parameter& parameter) {
|
const ThreadedList<ParserFormalParameters::Parameter>& parameters) {
|
||||||
bool is_duplicate = false;
|
for (auto parameter : parameters) {
|
||||||
bool is_simple = classifier()->is_simple_parameter_list();
|
bool is_duplicate = false;
|
||||||
auto name = is_simple || parameter.is_rest
|
bool is_simple = classifier()->is_simple_parameter_list();
|
||||||
? parameter.name
|
auto name = is_simple || parameter->is_rest
|
||||||
: ast_value_factory()->empty_string();
|
? parameter->name
|
||||||
auto mode = is_simple || parameter.is_rest ? VAR : TEMPORARY;
|
: ast_value_factory()->empty_string();
|
||||||
if (!is_simple) scope->SetHasNonSimpleParameters();
|
auto mode = is_simple || parameter->is_rest ? VAR : TEMPORARY;
|
||||||
bool is_optional = parameter.initializer != nullptr;
|
if (!is_simple) scope->SetHasNonSimpleParameters();
|
||||||
Variable* var =
|
bool is_optional = parameter->initializer != nullptr;
|
||||||
scope->DeclareParameter(name, mode, is_optional, parameter.is_rest,
|
Variable* var =
|
||||||
&is_duplicate, ast_value_factory());
|
scope->DeclareParameter(name, mode, is_optional, parameter->is_rest,
|
||||||
if (is_duplicate) {
|
&is_duplicate, ast_value_factory());
|
||||||
classifier()->RecordDuplicateFormalParameterError(scanner()->location());
|
if (is_duplicate &&
|
||||||
}
|
classifier()->is_valid_formal_parameter_list_without_duplicates()) {
|
||||||
if (is_sloppy(scope->language_mode())) {
|
classifier()->RecordDuplicateFormalParameterError(
|
||||||
// TODO(sigurds) Mark every parameter as maybe assigned. This is a
|
scanner()->location());
|
||||||
// conservative approximation necessary to account for parameters
|
}
|
||||||
// that are assigned via the arguments array.
|
if (is_sloppy(scope->language_mode())) {
|
||||||
var->set_maybe_assigned();
|
// TODO(sigurds) Mark every parameter as maybe assigned. This is a
|
||||||
|
// conservative approximation necessary to account for parameters
|
||||||
|
// that are assigned via the arguments array.
|
||||||
|
var->set_maybe_assigned();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +752,8 @@ class PreParserFactory {
|
|||||||
struct PreParserFormalParameters : FormalParametersBase {
|
struct PreParserFormalParameters : FormalParametersBase {
|
||||||
explicit PreParserFormalParameters(DeclarationScope* scope)
|
explicit PreParserFormalParameters(DeclarationScope* scope)
|
||||||
: FormalParametersBase(scope) {}
|
: FormalParametersBase(scope) {}
|
||||||
PreParserIdentifier at(int i) { return PreParserIdentifier(); } // Dummy
|
|
||||||
|
void* params = nullptr; // Dummy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1440,8 +1441,8 @@ class PreParser : public ParserBase<PreParser> {
|
|||||||
parameters->UpdateArityAndFunctionLength(!initializer.IsEmpty(), is_rest);
|
parameters->UpdateArityAndFunctionLength(!initializer.IsEmpty(), is_rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
V8_INLINE void DeclareFormalParameter(DeclarationScope* scope,
|
V8_INLINE void DeclareFormalParameters(DeclarationScope* scope,
|
||||||
PreParserIdentifier parameter) {
|
void* parameters) {
|
||||||
if (!classifier()->is_simple_parameter_list()) {
|
if (!classifier()->is_simple_parameter_list()) {
|
||||||
scope->SetHasNonSimpleParameters();
|
scope->SetHasNonSimpleParameters();
|
||||||
}
|
}
|
||||||
|
22
src/utils.h
22
src/utils.h
@ -1627,9 +1627,31 @@ class ThreadedList final {
|
|||||||
friend class ThreadedList;
|
friend class ThreadedList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ConstIterator final {
|
||||||
|
public:
|
||||||
|
ConstIterator& operator++() {
|
||||||
|
entry_ = (*entry_)->next();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
bool operator!=(const ConstIterator& other) {
|
||||||
|
return entry_ != other.entry_;
|
||||||
|
}
|
||||||
|
const T* operator*() const { return *entry_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ConstIterator(T* const* entry) : entry_(entry) {}
|
||||||
|
|
||||||
|
T* const* entry_;
|
||||||
|
|
||||||
|
friend class ThreadedList;
|
||||||
|
};
|
||||||
|
|
||||||
Iterator begin() { return Iterator(&head_); }
|
Iterator begin() { return Iterator(&head_); }
|
||||||
Iterator end() { return Iterator(tail_); }
|
Iterator end() { return Iterator(tail_); }
|
||||||
|
|
||||||
|
ConstIterator begin() const { return ConstIterator(&head_); }
|
||||||
|
ConstIterator end() const { return ConstIterator(tail_); }
|
||||||
|
|
||||||
void Rewind(Iterator reset_point) {
|
void Rewind(Iterator reset_point) {
|
||||||
tail_ = reset_point.entry_;
|
tail_ = reset_point.entry_;
|
||||||
*tail_ = nullptr;
|
*tail_ = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user