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

[parser] Skipping inner funcs: simplify rest parameter handling.

With the params (a, b, ...c) the param / variable declaration order used to be
"temp, temp, c, a, b". Now it is "temp, temp, a, b, c" as you'd expect. This
makes it easier for PreParser to match the parameter order of Parser.

R=verwaest@chromium.org
BUG=v8:5516

Change-Id: I79da04ef3f812bf52c032bed6263c009fecb7988
Reviewed-on: https://chromium-review.googlesource.com/447677Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43490}
parent a6b20adb
...@@ -2913,10 +2913,10 @@ Block* Parser::BuildParameterInitializationBlock( ...@@ -2913,10 +2913,10 @@ Block* Parser::BuildParameterInitializationBlock(
const ParserFormalParameters& parameters, bool* ok) { const ParserFormalParameters& parameters, bool* ok) {
DCHECK(!parameters.is_simple); DCHECK(!parameters.is_simple);
DCHECK(scope()->is_function_scope()); DCHECK(scope()->is_function_scope());
DCHECK_EQ(scope(), parameters.scope);
Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition); Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
int index = 0; int index = 0;
for (auto parameter : parameters.params) { for (auto parameter : parameters.params) {
if (parameter->is_nondestructuring_rest()) break;
DeclarationDescriptor descriptor; DeclarationDescriptor descriptor;
descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
descriptor.scope = scope(); descriptor.scope = scope();
......
...@@ -157,11 +157,6 @@ struct ParserFormalParameters : FormalParametersBase { ...@@ -157,11 +157,6 @@ struct ParserFormalParameters : FormalParametersBase {
return pattern->IsVariableProxy() && initializer == nullptr && !is_rest; return pattern->IsVariableProxy() && initializer == nullptr && !is_rest;
} }
bool is_nondestructuring_rest() const {
DCHECK_IMPLIES(is_rest, initializer == nullptr);
return is_rest && pattern->IsVariableProxy();
}
Parameter** next() { return &next_parameter; } Parameter** next() { return &next_parameter; }
Parameter* const* next() const { return &next_parameter; } Parameter* const* next() const { return &next_parameter; }
}; };
...@@ -1080,11 +1075,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -1080,11 +1075,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
if (!is_simple) scope->SetHasNonSimpleParameters(); if (!is_simple) scope->SetHasNonSimpleParameters();
for (auto parameter : parameters) { for (auto parameter : parameters) {
bool is_duplicate = false; bool is_duplicate = false;
bool use_name = is_simple || parameter->is_nondestructuring_rest();
bool is_optional = parameter->initializer != nullptr; bool is_optional = parameter->initializer != nullptr;
// If the parameter list is simple, declare the parameters normally with
// their names. If the parameter list is not simple, declare a temporary
// for each parameter - the corresponding named variable is declared by
// BuildParamerterInitializationBlock.
scope->DeclareParameter( scope->DeclareParameter(
use_name ? parameter->name : ast_value_factory()->empty_string(), is_simple ? parameter->name : ast_value_factory()->empty_string(),
use_name ? VAR : TEMPORARY, is_optional, parameter->is_rest, is_simple ? VAR : TEMPORARY, is_optional, parameter->is_rest,
&is_duplicate, ast_value_factory()); &is_duplicate, ast_value_factory());
if (is_duplicate && if (is_duplicate &&
classifier()->is_valid_formal_parameter_list_without_duplicates()) { classifier()->is_valid_formal_parameter_list_without_duplicates()) {
......
...@@ -791,19 +791,13 @@ class PreParserFactory { ...@@ -791,19 +791,13 @@ class PreParserFactory {
struct PreParserFormalParameters : FormalParametersBase { struct PreParserFormalParameters : FormalParametersBase {
struct Parameter : public ZoneObject { struct Parameter : public ZoneObject {
Parameter(PreParserExpression pattern, bool is_destructuring, bool is_rest) Parameter(ZoneList<VariableProxy*>* variables, bool is_rest)
: pattern(pattern), : variables_(variables), is_rest(is_rest) {}
is_destructuring(is_destructuring),
is_rest(is_rest) {}
Parameter** next() { return &next_parameter; } Parameter** next() { return &next_parameter; }
Parameter* const* next() const { return &next_parameter; } Parameter* const* next() const { return &next_parameter; }
bool is_nondestructuring_rest() const { ZoneList<VariableProxy*>* variables_;
return is_rest && !is_destructuring;
}
PreParserExpression pattern;
Parameter* next_parameter = nullptr; Parameter* next_parameter = nullptr;
bool is_destructuring : 1;
bool is_rest : 1; bool is_rest : 1;
}; };
explicit PreParserFormalParameters(DeclarationScope* scope) explicit PreParserFormalParameters(DeclarationScope* scope)
...@@ -1386,16 +1380,6 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1386,16 +1380,6 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE PreParserStatement BuildParameterInitializationBlock( V8_INLINE PreParserStatement BuildParameterInitializationBlock(
const PreParserFormalParameters& parameters, bool* ok) { const PreParserFormalParameters& parameters, bool* ok) {
if (track_unresolved_variables_) {
for (auto parameter : parameters.params) {
if (parameter->is_nondestructuring_rest()) break;
if (parameter->pattern.variables_ != nullptr) {
for (auto variable : *parameter->pattern.variables_) {
scope()->DeclareVariableName(variable->raw_name(), LET);
}
}
}
}
return PreParserStatement::Default(); return PreParserStatement::Default();
} }
...@@ -1617,7 +1601,7 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1617,7 +1601,7 @@ class PreParser : public ParserBase<PreParser> {
if (track_unresolved_variables_) { if (track_unresolved_variables_) {
DCHECK(FLAG_lazy_inner_functions); DCHECK(FLAG_lazy_inner_functions);
parameters->params.Add(new (zone()) PreParserFormalParameters::Parameter( parameters->params.Add(new (zone()) PreParserFormalParameters::Parameter(
pattern, !IsIdentifier(pattern), is_rest)); pattern.variables_, is_rest));
} }
parameters->UpdateArityAndFunctionLength(!initializer.IsEmpty(), is_rest); parameters->UpdateArityAndFunctionLength(!initializer.IsEmpty(), is_rest);
} }
...@@ -1630,13 +1614,11 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1630,13 +1614,11 @@ class PreParser : public ParserBase<PreParser> {
if (track_unresolved_variables_) { if (track_unresolved_variables_) {
DCHECK(FLAG_lazy_inner_functions); DCHECK(FLAG_lazy_inner_functions);
for (auto parameter : parameters) { for (auto parameter : parameters) {
bool use_name = is_simple || parameter->is_nondestructuring_rest(); if (parameter->variables_ != nullptr) {
if (use_name) { for (auto variable : (*parameter->variables_)) {
DCHECK_NOT_NULL(parameter->pattern.variables_); scope->DeclareParameterName(
DCHECK_EQ(parameter->pattern.variables_->length(), 1); variable->raw_name(), parameter->is_rest, ast_value_factory());
auto variable = (*parameter->pattern.variables_)[0]; }
scope->DeclareParameterName(variable->raw_name(), parameter->is_rest,
ast_value_factory());
} }
} }
} }
......
...@@ -11,14 +11,17 @@ snippet: " ...@@ -11,14 +11,17 @@ snippet: "
function f(...restArgs) { return restArgs; } function f(...restArgs) { return restArgs; }
f(); f();
" "
frame size: 1 frame size: 2
parameter count: 1 parameter count: 1
bytecode array length: 6 bytecode array length: 13
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(0), B(Star), R(0),
B(LdaTheHole),
B(Star), R(1),
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 26 S> */ B(Nop), B(Mov), R(0), R(1),
/* 26 S> */ B(Ldar), R(1),
/* 43 S> */ B(Return), /* 43 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -31,17 +34,20 @@ snippet: " ...@@ -31,17 +34,20 @@ snippet: "
function f(a, ...restArgs) { return restArgs; } function f(a, ...restArgs) { return restArgs; }
f(); f();
" "
frame size: 2 frame size: 3
parameter count: 2 parameter count: 2
bytecode array length: 13 bytecode array length: 19
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(0), B(Star), R(0),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(1), B(Star), R(1),
B(LdaTheHole),
B(Star), R(2),
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
B(Mov), R(arg0), R(1), B(Mov), R(arg0), R(1),
/* 29 S> */ B(Ldar), R(0), B(Mov), R(0), R(2),
/* 29 S> */ B(Ldar), R(2),
/* 46 S> */ B(Return), /* 46 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -54,18 +60,21 @@ snippet: " ...@@ -54,18 +60,21 @@ snippet: "
function f(a, ...restArgs) { return restArgs[0]; } function f(a, ...restArgs) { return restArgs[0]; }
f(); f();
" "
frame size: 2 frame size: 3
parameter count: 2 parameter count: 2
bytecode array length: 15 bytecode array length: 21
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(0), B(Star), R(0),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(1), B(Star), R(1),
B(LdaTheHole),
B(Star), R(2),
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
B(Mov), R(arg0), R(1), B(Mov), R(arg0), R(1),
B(Mov), R(0), R(2),
/* 29 S> */ B(LdaZero), /* 29 S> */ B(LdaZero),
/* 44 E> */ B(LdaKeyedProperty), R(0), U8(2), /* 44 E> */ B(LdaKeyedProperty), R(2), U8(2),
/* 49 S> */ B(Return), /* 49 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -78,24 +87,27 @@ snippet: " ...@@ -78,24 +87,27 @@ snippet: "
function f(a, ...restArgs) { return restArgs[0] + arguments[0]; } function f(a, ...restArgs) { return restArgs[0] + arguments[0]; }
f(); f();
" "
frame size: 4 frame size: 5
parameter count: 2 parameter count: 2
bytecode array length: 27 bytecode array length: 33
bytecodes: [ bytecodes: [
B(CreateUnmappedArguments), B(CreateUnmappedArguments),
B(Star), R(2), B(Star), R(3),
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(0), B(Star), R(0),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(1), B(Star), R(1),
B(LdaTheHole),
B(Star), R(2),
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
B(Mov), R(arg0), R(1), B(Mov), R(arg0), R(1),
B(Mov), R(0), R(2),
/* 29 S> */ B(LdaZero), /* 29 S> */ B(LdaZero),
/* 44 E> */ B(LdaKeyedProperty), R(0), U8(2), /* 44 E> */ B(LdaKeyedProperty), R(2), U8(2),
B(Star), R(3), B(Star), R(4),
B(LdaZero), B(LdaZero),
/* 59 E> */ B(LdaKeyedProperty), R(2), U8(4), /* 59 E> */ B(LdaKeyedProperty), R(3), U8(4),
/* 48 E> */ B(Add), R(3), U8(6), /* 48 E> */ B(Add), R(4), U8(6),
/* 64 S> */ B(Return), /* 64 S> */ B(Return),
] ]
constant pool: [ constant pool: [
......
...@@ -51,34 +51,37 @@ snippet: " ...@@ -51,34 +51,37 @@ snippet: "
test = new B(1, 2, 3).constructor; test = new B(1, 2, 3).constructor;
})(); })();
" "
frame size: 6 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 59 bytecode array length: 65
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(2), B(Star), R(2),
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(LdaTheHole),
B(Star), R(3),
/* 128 E> */ B(StackCheck), /* 128 E> */ B(StackCheck),
B(Mov), R(2), R(3),
/* 140 S> */ B(Ldar), R(1), /* 140 S> */ B(Ldar), R(1),
B(GetSuperConstructor), R(3), B(GetSuperConstructor), R(4),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(4), B(Star), R(5),
B(Ldar), R(0), B(Ldar), R(0),
B(Mov), R(2), R(5), B(Mov), R(2), R(6),
/* 140 E> */ B(ConstructWithSpread), R(3), R(4), U8(2), /* 140 E> */ B(ConstructWithSpread), R(4), R(5), U8(2),
B(Star), R(3), B(Star), R(4),
B(Ldar), R(this), B(Ldar), R(this),
B(JumpIfNotHole), U8(4), B(JumpIfNotHole), U8(4),
B(Jump), U8(7), B(Jump), U8(7),
/* 140 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0), /* 140 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0),
B(Mov), R(3), R(this), B(Mov), R(4), R(this),
B(Ldar), R(this), B(Ldar), R(this),
B(JumpIfNotHole), U8(11), B(JumpIfNotHole), U8(11),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star), R(3), B(Star), R(4),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
/* 159 S> */ B(Return), /* 159 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -100,46 +103,49 @@ snippet: " ...@@ -100,46 +103,49 @@ snippet: "
test = new B(1, 2, 3).constructor; test = new B(1, 2, 3).constructor;
})(); })();
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 92 bytecode array length: 98
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(2), B(Star), R(2),
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(LdaTheHole),
B(Star), R(3),
/* 128 E> */ B(StackCheck), /* 128 E> */ B(StackCheck),
B(Mov), R(2), R(3),
/* 140 S> */ B(LdaUndefined), /* 140 S> */ B(LdaUndefined),
B(Star), R(3),
/* 140 E> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1),
B(Star), R(4), B(Star), R(4),
B(LdaUndefined), /* 140 E> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1),
B(Star), R(5), B(Star), R(5),
B(CreateArrayLiteral), U8(0), U8(2), U8(9),
B(Star), R(6),
B(LdaUndefined), B(LdaUndefined),
B(Star), R(6),
B(CreateArrayLiteral), U8(0), U8(2), U8(9),
B(Star), R(7), B(Star), R(7),
B(Mov), R(2), R(8), B(LdaUndefined),
/* 152 E> */ B(CallJSRuntime), U8(%spread_iterable), R(7), U8(2),
B(Star), R(7),
B(CreateArrayLiteral), U8(1), U8(3), U8(9),
B(Star), R(8), B(Star), R(8),
B(CallJSRuntime), U8(%spread_arguments), R(5), U8(4), B(Mov), R(2), R(9),
B(Star), R(5), /* 152 E> */ B(CallJSRuntime), U8(%spread_iterable), R(8), U8(2),
B(Mov), R(0), R(6), B(Star), R(8),
/* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(3), U8(4), B(CreateArrayLiteral), U8(1), U8(3), U8(9),
B(Star), R(3), B(Star), R(9),
B(CallJSRuntime), U8(%spread_arguments), R(6), U8(4),
B(Star), R(6),
B(Mov), R(0), R(7),
/* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(4), U8(4),
B(Star), R(4),
B(Ldar), R(this), B(Ldar), R(this),
B(JumpIfNotHole), U8(4), B(JumpIfNotHole), U8(4),
B(Jump), U8(7), B(Jump), U8(7),
/* 140 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0), /* 140 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0),
B(Mov), R(3), R(this), B(Mov), R(4), R(this),
B(Ldar), R(this), B(Ldar), R(this),
B(JumpIfNotHole), U8(11), B(JumpIfNotHole), U8(11),
B(LdaConstant), U8(2), B(LdaConstant), U8(2),
B(Star), R(3), B(Star), R(4),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
/* 162 S> */ B(Return), /* 162 S> */ B(Return),
] ]
constant pool: [ constant pool: [
......
...@@ -55,7 +55,23 @@ class ScopeTestHelper { ...@@ -55,7 +55,23 @@ class ScopeTestHelper {
CHECK_EQ(data->backing_store_[index++], local_name->raw_data()[i]); CHECK_EQ(data->backing_store_[index++], local_name->raw_data()[i]);
} }
#endif #endif
CHECK_EQ(data->backing_store_[index++], local->location()); // Allow PreParser to not distinguish between parameter / local; that
// information is not relevant for deciding the allocation (potentially
// skipped inner functions don't affect it).
int location = data->backing_store_[index++];
switch (local->location()) {
case PARAMETER:
case LOCAL:
CHECK(location == PARAMETER || location == LOCAL);
break;
case CONTEXT:
case UNALLOCATED:
CHECK_EQ(location, local->location());
break;
default:
CHECK(false);
}
if (precise_maybe_assigned) { if (precise_maybe_assigned) {
CHECK_EQ(data->backing_store_[index++], local->maybe_assigned()); CHECK_EQ(data->backing_store_[index++], local->maybe_assigned());
} else { } else {
......
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