| Index: src/parsing/parser.cc
 | 
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
 | 
| index 1d26e77039d855a2be83214a2a186e200c498e5e..4ba5dd2dfd3e2afd16d808b552b479f971be3da9 100644
 | 
| --- a/src/parsing/parser.cc
 | 
| +++ b/src/parsing/parser.cc
 | 
| @@ -15,6 +15,7 @@
 | 
|  #include "src/base/platform/platform.h"
 | 
|  #include "src/char-predicates-inl.h"
 | 
|  #include "src/messages.h"
 | 
| +#include "src/parsing/declaration-descriptor.h"
 | 
|  #include "src/parsing/duplicate-finder.h"
 | 
|  #include "src/parsing/parameter-initializer-rewriter.h"
 | 
|  #include "src/parsing/parse-info.h"
 | 
| @@ -1666,118 +1667,13 @@ Declaration* Parser::DeclareVariable(const AstRawString* name,
 | 
|                             scanner()->location().end_pos);
 | 
|    Declaration* declaration =
 | 
|        factory()->NewVariableDeclaration(proxy, this->scope(), pos);
 | 
| -  Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, CHECK_OK);
 | 
| +  this->scope()->DeclareVariableOrParameter(
 | 
| +      declaration, DeclarationDescriptor::NORMAL, mode, init,
 | 
| +      allow_harmony_restrictive_generators(), &pending_error_handler_,
 | 
| +      use_counts_, CHECK_OK);
 | 
|    return declaration;
 | 
|  }
 | 
|  
 | 
| -Variable* Parser::Declare(Declaration* declaration,
 | 
| -                          DeclarationDescriptor::Kind declaration_kind,
 | 
| -                          VariableMode mode, InitializationFlag init, bool* ok,
 | 
| -                          Scope* scope) {
 | 
| -  DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY);
 | 
| -
 | 
| -  VariableProxy* proxy = declaration->proxy();
 | 
| -  DCHECK(proxy->raw_name() != NULL);
 | 
| -  const AstRawString* name = proxy->raw_name();
 | 
| -
 | 
| -  if (scope == nullptr) scope = this->scope();
 | 
| -  if (mode == VAR) scope = scope->GetDeclarationScope();
 | 
| -  DCHECK(!scope->is_catch_scope());
 | 
| -  DCHECK(!scope->is_with_scope());
 | 
| -  DCHECK(scope->is_declaration_scope() ||
 | 
| -         (IsLexicalVariableMode(mode) && scope->is_block_scope()));
 | 
| -
 | 
| -  bool is_function_declaration = declaration->IsFunctionDeclaration();
 | 
| -
 | 
| -  Variable* var = NULL;
 | 
| -  if (scope->is_eval_scope() && is_sloppy(scope->language_mode()) &&
 | 
| -      mode == VAR) {
 | 
| -    // In a var binding in a sloppy direct eval, pollute the enclosing scope
 | 
| -    // with this new binding by doing the following:
 | 
| -    // The proxy is bound to a lookup variable to force a dynamic declaration
 | 
| -    // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
 | 
| -    Variable::Kind kind = Variable::NORMAL;
 | 
| -    // TODO(sigurds) figure out if kNotAssigned is OK here
 | 
| -    var = new (zone()) Variable(scope, name, mode, kind, init, kNotAssigned);
 | 
| -    var->AllocateTo(VariableLocation::LOOKUP, -1);
 | 
| -  } else {
 | 
| -    // Declare the variable in the declaration scope.
 | 
| -    var = scope->LookupLocal(name);
 | 
| -    if (var == NULL) {
 | 
| -      // Declare the name.
 | 
| -      Variable::Kind kind = Variable::NORMAL;
 | 
| -      if (is_function_declaration) {
 | 
| -        kind = Variable::FUNCTION;
 | 
| -      }
 | 
| -      var = scope->DeclareLocal(name, mode, init, kind, kNotAssigned);
 | 
| -    } else if (IsLexicalVariableMode(mode) ||
 | 
| -               IsLexicalVariableMode(var->mode())) {
 | 
| -      // Allow duplicate function decls for web compat, see bug 4693.
 | 
| -      bool duplicate_allowed = false;
 | 
| -      if (is_sloppy(scope->language_mode()) && is_function_declaration &&
 | 
| -          var->is_function()) {
 | 
| -        DCHECK(IsLexicalVariableMode(mode) &&
 | 
| -               IsLexicalVariableMode(var->mode()));
 | 
| -        // If the duplication is allowed, then the var will show up
 | 
| -        // in the SloppyBlockFunctionMap and the new FunctionKind
 | 
| -        // will be a permitted duplicate.
 | 
| -        FunctionKind function_kind =
 | 
| -            declaration->AsFunctionDeclaration()->fun()->kind();
 | 
| -        duplicate_allowed =
 | 
| -            scope->GetDeclarationScope()->sloppy_block_function_map()->Lookup(
 | 
| -                const_cast<AstRawString*>(name), name->hash()) != nullptr &&
 | 
| -            !IsAsyncFunction(function_kind) &&
 | 
| -            !(allow_harmony_restrictive_generators() &&
 | 
| -              IsGeneratorFunction(function_kind));
 | 
| -      }
 | 
| -      if (duplicate_allowed) {
 | 
| -        ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
 | 
| -      } else {
 | 
| -        // The name was declared in this scope before; check for conflicting
 | 
| -        // re-declarations. We have a conflict if either of the declarations
 | 
| -        // is not a var (in script scope, we also have to ignore legacy const
 | 
| -        // for compatibility). There is similar code in runtime.cc in the
 | 
| -        // Declare functions. The function CheckConflictingVarDeclarations
 | 
| -        // checks for var and let bindings from different scopes whereas this
 | 
| -        // is a check for conflicting declarations within the same scope. This
 | 
| -        // check also covers the special case
 | 
| -        //
 | 
| -        // function () { let x; { var x; } }
 | 
| -        //
 | 
| -        // because the var declaration is hoisted to the function scope where
 | 
| -        // 'x' is already bound.
 | 
| -        DCHECK(IsDeclaredVariableMode(var->mode()));
 | 
| -        // In harmony we treat re-declarations as early errors. See
 | 
| -        // ES5 16 for a definition of early errors.
 | 
| -        if (declaration_kind == DeclarationDescriptor::NORMAL) {
 | 
| -          ReportMessage(MessageTemplate::kVarRedeclaration, name);
 | 
| -        } else {
 | 
| -          ReportMessage(MessageTemplate::kParamDupe);
 | 
| -        }
 | 
| -        *ok = false;
 | 
| -        return nullptr;
 | 
| -      }
 | 
| -    } else if (mode == VAR) {
 | 
| -      var->set_maybe_assigned();
 | 
| -    }
 | 
| -  }
 | 
| -  DCHECK_NOT_NULL(var);
 | 
| -
 | 
| -  // We add a declaration node for every declaration. The compiler
 | 
| -  // will only generate code if necessary. In particular, declarations
 | 
| -  // for inner local variables that do not represent functions won't
 | 
| -  // result in any generated code.
 | 
| -  //
 | 
| -  // This will lead to multiple declaration nodes for the
 | 
| -  // same variable if it is declared several times. This is not a
 | 
| -  // semantic issue, but it may be a performance issue since it may
 | 
| -  // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
 | 
| -  scope->AddDeclaration(declaration);
 | 
| -  proxy->BindTo(var);
 | 
| -  return var;
 | 
| -}
 | 
| -
 | 
| -
 | 
|  // Language extension which is only enabled for source files loaded
 | 
|  // through the API's extension mechanism.  A native function
 | 
|  // declaration is resolved by looking up the function through a
 | 
| @@ -1893,8 +1789,10 @@ Statement* Parser::ParseHoistableDeclaration(
 | 
|    VariableProxy* proxy = NewUnresolved(variable_name);
 | 
|    Declaration* declaration =
 | 
|        factory()->NewFunctionDeclaration(proxy, fun, scope(), pos);
 | 
| -  Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
 | 
| -          CHECK_OK);
 | 
| +  this->scope()->DeclareVariableOrParameter(
 | 
| +      declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
 | 
| +      allow_harmony_restrictive_generators(), &pending_error_handler_,
 | 
| +      use_counts_, CHECK_OK);
 | 
|    if (names) names->Add(variable_name, zone());
 | 
|    EmptyStatement* empty = factory()->NewEmptyStatement(kNoSourcePosition);
 | 
|    // Async functions don't undergo sloppy mode block scoped hoisting, and don't
 | 
| @@ -4763,8 +4661,11 @@ Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
 | 
|      // TODO(verwaest): declare via block_state.
 | 
|      Declaration* declaration =
 | 
|          factory()->NewVariableDeclaration(proxy, block_state.scope(), pos);
 | 
| -    Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
 | 
| -            DefaultInitializationFlag(CONST), CHECK_OK);
 | 
| +    this->scope()->DeclareVariableOrParameter(
 | 
| +        declaration, DeclarationDescriptor::NORMAL, CONST,
 | 
| +        DefaultInitializationFlag(CONST),
 | 
| +        allow_harmony_restrictive_generators(), &pending_error_handler_,
 | 
| +        use_counts_, CHECK_OK);
 | 
|    }
 | 
|  
 | 
|    Expression* extends = nullptr;
 | 
| @@ -5042,10 +4943,13 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope,
 | 
|          VariableProxy* proxy = scope->NewUnresolved(factory(), name);
 | 
|          Declaration* declaration =
 | 
|              factory()->NewVariableDeclaration(proxy, scope, kNoSourcePosition);
 | 
| -        Declare(declaration, DeclarationDescriptor::NORMAL, VAR,
 | 
| -                DefaultInitializationFlag(VAR), ok, scope);
 | 
| -        DCHECK(ok);  // Based on the preceding check, this should not fail
 | 
| -        if (!ok) return;
 | 
| +        scope->DeclareVariableOrParameter(
 | 
| +            declaration, DeclarationDescriptor::NORMAL, VAR,
 | 
| +            DefaultInitializationFlag(VAR),
 | 
| +            allow_harmony_restrictive_generators(), &pending_error_handler_,
 | 
| +            use_counts_, ok);
 | 
| +        DCHECK(*ok);  // Based on the preceding check, this should not fail
 | 
| +        if (!*ok) return;
 | 
|        }
 | 
|  
 | 
|        // Read from the local lexical scope and write to the function scope
 | 
| 
 |