| Index: src/preparser.h
|
| diff --git a/src/preparser.h b/src/preparser.h
|
| index fd82651a7e012a88c7e09c58c53732522853d121..57a93d8d4d183463d0797e76f3c933c1072c1333 100644
|
| --- a/src/preparser.h
|
| +++ b/src/preparser.h
|
| @@ -13,6 +13,7 @@
|
| #include "src/scanner.h"
|
| #include "src/scopes.h"
|
| #include "src/token.h"
|
| +#include "src/zone.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -42,7 +43,6 @@ namespace internal {
|
| // // Used by FunctionState and BlockState.
|
| // typedef Scope;
|
| // typedef GeneratorVariable;
|
| -// typedef Zone;
|
| // // Return types for traversing functions.
|
| // typedef Identifier;
|
| // typedef Expression;
|
| @@ -69,7 +69,7 @@ class ParserBase : public Traits {
|
| typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
|
|
|
| ParserBase(Scanner* scanner, uintptr_t stack_limit, v8::Extension* extension,
|
| - ParserRecorder* log, typename Traits::Type::Zone* zone,
|
| + ParserRecorder* log, Zone* zone,
|
| typename Traits::Type::Parser this_object)
|
| : Traits(this_object),
|
| parenthesized_function_(false),
|
| @@ -126,10 +126,7 @@ class ParserBase : public Traits {
|
| kDontAllowEvalOrArguments
|
| };
|
|
|
| - enum Mode {
|
| - PARSE_LAZILY,
|
| - PARSE_EAGERLY
|
| - };
|
| + enum Mode { PARSE_LAZILY, PARSE_EAGERLY, PARSE_INNER_FUNCTION_LAZILY };
|
|
|
| class Checkpoint;
|
| class ObjectLiteralChecker;
|
| @@ -217,7 +214,6 @@ class ParserBase : public Traits {
|
| FunctionState* outer_function_state_;
|
| typename Traits::Type::Scope** scope_stack_;
|
| typename Traits::Type::Scope* outer_scope_;
|
| - typename Traits::Type::Zone* extra_param_;
|
| typename Traits::Type::Factory* factory_;
|
|
|
| friend class ParserTraits;
|
| @@ -274,7 +270,7 @@ class ParserBase : public Traits {
|
| bool stack_overflow() const { return stack_overflow_; }
|
| void set_stack_overflow() { stack_overflow_ = true; }
|
| Mode mode() const { return mode_; }
|
| - typename Traits::Type::Zone* zone() const { return zone_; }
|
| + Zone* zone() const { return zone_; }
|
|
|
| INLINE(Token::Value peek()) {
|
| if (stack_overflow_) return Token::ILLEGAL;
|
| @@ -576,7 +572,7 @@ class ParserBase : public Traits {
|
| bool allow_arrow_functions_;
|
| bool allow_harmony_object_literals_;
|
|
|
| - typename Traits::Type::Zone* zone_; // Only used by Parser.
|
| + Zone* zone_;
|
| };
|
|
|
|
|
| @@ -934,12 +930,27 @@ class PreParserStatementList {
|
|
|
| class PreParserScope {
|
| public:
|
| - explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type,
|
| - void* = NULL)
|
| - : scope_type_(scope_type) {
|
| + PreParserScope(PreParserScope* outer_scope, ScopeType scope_type, Zone* zone,
|
| + bool log_identifiers)
|
| + : outer_scope_(outer_scope),
|
| + scope_type_(scope_type),
|
| + zone_(zone),
|
| + declared_variables_(NULL),
|
| + unbound_variables_(NULL) {
|
| strict_mode_ = outer_scope ? outer_scope->strict_mode() : SLOPPY;
|
| + if (log_identifiers) {
|
| + ZoneAllocationPolicy allocator(zone);
|
| + declared_variables_ = new (zone->New(sizeof(ZoneHashMap)))
|
| + ZoneHashMap(ZoneHashMap::PointersMatch,
|
| + ZoneHashMap::kDefaultHashMapCapacity, allocator);
|
| + unbound_variables_ = new (zone->New(sizeof(ZoneHashMap)))
|
| + ZoneHashMap(ZoneHashMap::PointersMatch,
|
| + ZoneHashMap::kDefaultHashMapCapacity, allocator);
|
| + }
|
| }
|
|
|
| + ~PreParserScope();
|
| +
|
| ScopeType type() { return scope_type_; }
|
| StrictMode strict_mode() const { return strict_mode_; }
|
| void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
|
| @@ -957,12 +968,44 @@ class PreParserScope {
|
| void RecordArgumentsUsage() {}
|
| void RecordThisUsage() {}
|
|
|
| + bool is_eval_scope() const { return scope_type_ == EVAL_SCOPE; }
|
| + bool is_function_scope() const {
|
| + return scope_type_ == FUNCTION_SCOPE || scope_type_ == ARROW_SCOPE;
|
| + }
|
| + bool is_module_scope() const { return scope_type_ == MODULE_SCOPE; }
|
| + bool is_global_scope() const { return scope_type_ == GLOBAL_SCOPE; }
|
| + bool is_declaration_scope() const {
|
| + return is_eval_scope() || is_function_scope() || is_module_scope() ||
|
| + is_global_scope();
|
| + }
|
| +
|
| + // The scope immediately surrounding this scope, or NULL.
|
| + PreParserScope* outer_scope() const { return outer_scope_; }
|
| +
|
| + // Walk up the scope chain and return the scope where var declarations will be
|
| + // hoisted to (could be this).
|
| + PreParserScope* DeclarationScope();
|
| +
|
| + // Record a variable declaration in the current declaration scope
|
| + void Declare(const AstRawString* identifier, bool lexical = false);
|
| +
|
| + // Record the usage of a variable in an identifier expression. If the variable
|
| + // was not declared in this scope, we report it to the full parser so it will
|
| + // be context-allocated.
|
| + void RecordVariableUsage(const AstRawString* identifier);
|
| +
|
| + void LogUnboundVariables(ParserRecorder* recorder);
|
| +
|
| // Allow scope->Foo() to work.
|
| PreParserScope* operator->() { return this; }
|
|
|
| private:
|
| + PreParserScope* outer_scope_;
|
| ScopeType scope_type_;
|
| StrictMode strict_mode_;
|
| + Zone* zone_;
|
| + ZoneHashMap* declared_variables_;
|
| + ZoneHashMap* unbound_variables_;
|
| };
|
|
|
|
|
| @@ -1111,13 +1154,11 @@ class PreParserTraits {
|
|
|
| // Used by FunctionState and BlockState.
|
| typedef PreParserScope Scope;
|
| - typedef PreParserScope ScopePtr;
|
| + typedef PreParserScope ScopePtr; // Return type of NewScope()
|
| inline static Scope* ptr_to_scope(ScopePtr& scope) { return &scope; }
|
|
|
| // PreParser doesn't need to store generator variables.
|
| typedef void GeneratorVariable;
|
| - // No interaction with Zones.
|
| - typedef void Zone;
|
|
|
| typedef int AstProperties;
|
| typedef Vector<PreParserIdentifier> ParameterIdentifierVector;
|
| @@ -1210,9 +1251,10 @@ class PreParserTraits {
|
| static void CheckAssigningFunctionLiteralToProperty(
|
| PreParserExpression left, PreParserExpression right) {}
|
|
|
| - // PreParser doesn't need to keep track of eval calls.
|
| - static void CheckPossibleEvalCall(PreParserExpression expression,
|
| - PreParserScope* scope) {}
|
| + // Need to record direct calls to eval so every variable in the enclosing
|
| + // scope gets allocated
|
| + void CheckPossibleEvalCall(PreParserExpression expression,
|
| + PreParserScope* scope);
|
|
|
| static PreParserExpression MarkExpressionAsAssigned(
|
| PreParserExpression expression) {
|
| @@ -1221,6 +1263,8 @@ class PreParserTraits {
|
| return expression;
|
| }
|
|
|
| + void RecordCurrentSymbolAsIdentifierExpression();
|
| +
|
| bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
|
| PreParserExpression y,
|
| Token::Value op,
|
| @@ -1246,9 +1290,8 @@ class PreParserTraits {
|
| const char* type, Handle<Object> arg, int pos) {
|
| return PreParserExpression::Default();
|
| }
|
| - PreParserScope NewScope(PreParserScope* outer_scope, ScopeType scope_type) {
|
| - return PreParserScope(outer_scope, scope_type);
|
| - }
|
| + inline PreParserScope NewScope(PreParserScope* outer_scope,
|
| + ScopeType scope_type);
|
|
|
| // Reporting errors.
|
| void ReportMessageAt(Scanner::Location location,
|
| @@ -1339,15 +1382,15 @@ class PreParserTraits {
|
| return PreParserExpression::Default();
|
| }
|
|
|
| - static PreParserExpressionList NewExpressionList(int size, void* zone) {
|
| + static PreParserExpressionList NewExpressionList(int size, Zone* zone) {
|
| return PreParserExpressionList();
|
| }
|
|
|
| - static PreParserStatementList NewStatementList(int size, void* zone) {
|
| + static PreParserStatementList NewStatementList(int size, Zone* zone) {
|
| return PreParserStatementList();
|
| }
|
|
|
| - static PreParserExpressionList NewPropertyList(int size, void* zone) {
|
| + static PreParserExpressionList NewPropertyList(int size, Zone* zone) {
|
| return PreParserExpressionList();
|
| }
|
|
|
| @@ -1412,16 +1455,20 @@ class PreParser : public ParserBase<PreParserTraits> {
|
| kPreParseSuccess
|
| };
|
|
|
| - PreParser(Scanner* scanner, ParserRecorder* log, uintptr_t stack_limit)
|
| - : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, NULL,
|
| - this) {}
|
| + PreParser(Scanner* scanner, ParserRecorder* log,
|
| + AstValueFactory* ast_value_factory, Zone* zone,
|
| + uintptr_t stack_limit)
|
| + : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, zone,
|
| + this),
|
| + ast_value_factory_(ast_value_factory),
|
| + log_identifiers_(false) {}
|
|
|
| // Pre-parse the program from the character stream; returns true on
|
| // success (even if parsing failed, the pre-parse data successfully
|
| // captured the syntax error), and false if a stack-overflow happened
|
| // during parsing.
|
| PreParseResult PreParseProgram() {
|
| - PreParserScope scope(scope_, GLOBAL_SCOPE);
|
| + PreParserScope scope = NewScope(scope_, GLOBAL_SCOPE);
|
| PreParserFactory factory(NULL);
|
| FunctionState top_scope(&function_state_, &scope_, &scope, &factory);
|
| bool ok = true;
|
| @@ -1444,8 +1491,8 @@ class PreParser : public ParserBase<PreParserTraits> {
|
| // keyword and parameters, and have consumed the initial '{'.
|
| // At return, unless an error occurred, the scanner is positioned before the
|
| // the final '}'.
|
| - PreParseResult PreParseLazyFunction(StrictMode strict_mode,
|
| - bool is_generator,
|
| + PreParseResult PreParseLazyFunction(StrictMode strict_mode, bool is_generator,
|
| + bool log_identifiers,
|
| ParserRecorder* log);
|
|
|
| private:
|
| @@ -1521,7 +1568,14 @@ class PreParser : public ParserBase<PreParserTraits> {
|
| FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
|
| void ParseLazyFunctionLiteralBody(bool* ok);
|
|
|
| + PreParserScope NewScope(PreParserScope* outer_scope, ScopeType scope_type) {
|
| + return PreParserScope(outer_scope, scope_type, zone(), log_identifiers_);
|
| + }
|
| +
|
| bool CheckInOrOf(bool accept_OF);
|
| +
|
| + AstValueFactory* ast_value_factory_;
|
| + bool log_identifiers_;
|
| };
|
|
|
|
|
| @@ -1546,6 +1600,12 @@ PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
|
| }
|
|
|
|
|
| +PreParserScope PreParserTraits::NewScope(PreParserScope* outer_scope,
|
| + ScopeType scope_type) {
|
| + return pre_parser_->NewScope(outer_scope, scope_type);
|
| +}
|
| +
|
| +
|
| template <class Traits>
|
| ParserBase<Traits>::FunctionState::FunctionState(
|
| FunctionState** function_state_stack,
|
| @@ -1767,6 +1827,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
|
| case Token::FUTURE_STRICT_RESERVED_WORD: {
|
| // Using eval or arguments in this context is OK even in strict mode.
|
| IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| + this->RecordCurrentSymbolAsIdentifierExpression();
|
| result = this->ExpressionFromIdentifier(name, pos, scope_, factory());
|
| break;
|
| }
|
| @@ -2018,6 +2079,7 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
|
| } else if (!in_class && allow_harmony_object_literals_ &&
|
| Token::IsIdentifier(name_token, strict_mode(),
|
| this->is_generator())) {
|
| + this->RecordCurrentSymbolAsIdentifierExpression();
|
| value = this->ExpressionFromIdentifier(name, next_pos, scope_, factory());
|
|
|
| } else {
|
|
|