diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
commit | 33af2720f26c2b25bc7f75ce7eb454ff99db6d35 (patch) | |
tree | 9a38f0c96420edf503eebd6325dd8d2d8249f653 /deps/v8/src/parser.cc | |
parent | 6afdca885adeeeed9eef8cbb01c3d97af0bc084d (diff) | |
download | node-new-33af2720f26c2b25bc7f75ce7eb454ff99db6d35.tar.gz |
Upgrade V8 to 3.4.8
Diffstat (limited to 'deps/v8/src/parser.cc')
-rw-r--r-- | deps/v8/src/parser.cc | 1315 |
1 files changed, 592 insertions, 723 deletions
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 6d462bc53c..4e5ba1389a 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -28,7 +28,7 @@ #include "v8.h" #include "api.h" -#include "ast.h" +#include "ast-inl.h" #include "bootstrapper.h" #include "codegen.h" #include "compiler.h" @@ -41,9 +41,6 @@ #include "scopeinfo.h" #include "string-stream.h" -#include "ast-inl.h" -#include "jump-target-inl.h" - namespace v8 { namespace internal { @@ -88,12 +85,13 @@ class PositionStack { RegExpBuilder::RegExpBuilder() - : pending_empty_(false), - characters_(NULL), - terms_(), - alternatives_() + : zone_(Isolate::Current()->zone()), + pending_empty_(false), + characters_(NULL), + terms_(), + alternatives_() #ifdef DEBUG - , last_added_(ADD_NONE) + , last_added_(ADD_NONE) #endif {} @@ -101,7 +99,7 @@ RegExpBuilder::RegExpBuilder() void RegExpBuilder::FlushCharacters() { pending_empty_ = false; if (characters_ != NULL) { - RegExpTree* atom = new RegExpAtom(characters_->ToConstVector()); + RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector()); characters_ = NULL; text_.Add(atom); LAST(ADD_ATOM); @@ -117,7 +115,7 @@ void RegExpBuilder::FlushText() { } else if (num_text == 1) { terms_.Add(text_.last()); } else { - RegExpText* text = new RegExpText(); + RegExpText* text = new(zone()) RegExpText(); for (int i = 0; i < num_text; i++) text_.Get(i)->AppendToText(text); terms_.Add(text); @@ -129,7 +127,7 @@ void RegExpBuilder::FlushText() { void RegExpBuilder::AddCharacter(uc16 c) { pending_empty_ = false; if (characters_ == NULL) { - characters_ = new ZoneList<uc16>(4); + characters_ = new(zone()) ZoneList<uc16>(4); } characters_->Add(c); LAST(ADD_CHAR); @@ -178,7 +176,7 @@ void RegExpBuilder::FlushTerms() { } else if (num_terms == 1) { alternative = terms_.last(); } else { - alternative = new RegExpAlternative(terms_.GetList()); + alternative = new(zone()) RegExpAlternative(terms_.GetList()); } alternatives_.Add(alternative); terms_.Clear(); @@ -195,7 +193,7 @@ RegExpTree* RegExpBuilder::ToRegExp() { if (num_alternatives == 1) { return alternatives_.last(); } - return new RegExpDisjunction(alternatives_.GetList()); + return new(zone()) RegExpDisjunction(alternatives_.GetList()); } @@ -214,11 +212,11 @@ void RegExpBuilder::AddQuantifierToAtom(int min, int num_chars = char_vector.length(); if (num_chars > 1) { Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1); - text_.Add(new RegExpAtom(prefix)); + text_.Add(new(zone()) RegExpAtom(prefix)); char_vector = char_vector.SubVector(num_chars - 1, num_chars); } characters_ = NULL; - atom = new RegExpAtom(char_vector); + atom = new(zone()) RegExpAtom(char_vector); FlushText(); } else if (text_.length() > 0) { ASSERT(last_added_ == ADD_ATOM); @@ -241,98 +239,11 @@ void RegExpBuilder::AddQuantifierToAtom(int min, UNREACHABLE(); return; } - terms_.Add(new RegExpQuantifier(min, max, type, atom)); + terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom)); LAST(ADD_TERM); } -// A temporary scope stores information during parsing, just like -// a plain scope. However, temporary scopes are not kept around -// after parsing or referenced by syntax trees so they can be stack- -// allocated and hence used by the pre-parser. -class TemporaryScope BASE_EMBEDDED { - public: - explicit TemporaryScope(TemporaryScope** variable); - ~TemporaryScope(); - - int NextMaterializedLiteralIndex() { - int next_index = - materialized_literal_count_ + JSFunction::kLiteralsPrefixSize; - materialized_literal_count_++; - return next_index; - } - int materialized_literal_count() { return materialized_literal_count_; } - - void SetThisPropertyAssignmentInfo( - bool only_simple_this_property_assignments, - Handle<FixedArray> this_property_assignments) { - only_simple_this_property_assignments_ = - only_simple_this_property_assignments; - this_property_assignments_ = this_property_assignments; - } - bool only_simple_this_property_assignments() { - return only_simple_this_property_assignments_; - } - Handle<FixedArray> this_property_assignments() { - return this_property_assignments_; - } - - void AddProperty() { expected_property_count_++; } - int expected_property_count() { return expected_property_count_; } - - void AddLoop() { loop_count_++; } - bool ContainsLoops() const { return loop_count_ > 0; } - - bool StrictMode() { return strict_mode_; } - void EnableStrictMode() { - strict_mode_ = FLAG_strict_mode; - } - - private: - // Captures the number of literals that need materialization in the - // function. Includes regexp literals, and boilerplate for object - // and array literals. - int materialized_literal_count_; - - // Properties count estimation. - int expected_property_count_; - - // Keeps track of assignments to properties of this. Used for - // optimizing constructors. - bool only_simple_this_property_assignments_; - Handle<FixedArray> this_property_assignments_; - - // Captures the number of loops inside the scope. - int loop_count_; - - // Parsing strict mode code. - bool strict_mode_; - - // Bookkeeping - TemporaryScope** variable_; - TemporaryScope* parent_; -}; - - -TemporaryScope::TemporaryScope(TemporaryScope** variable) - : materialized_literal_count_(0), - expected_property_count_(0), - only_simple_this_property_assignments_(false), - this_property_assignments_(Factory::empty_fixed_array()), - loop_count_(0), - variable_(variable), - parent_(*variable) { - // Inherit the strict mode from the parent scope. - strict_mode_ = (parent_ != NULL) && parent_->strict_mode_; - *variable = this; -} - - -TemporaryScope::~TemporaryScope() { - *variable_ = parent_; -} - - Handle<String> Parser::LookupSymbol(int symbol_id) { // Length of symbol cache is the number of identified symbols. // If we are larger than that, or negative, it's not a cached symbol. @@ -341,9 +252,11 @@ Handle<String> Parser::LookupSymbol(int symbol_id) { if (static_cast<unsigned>(symbol_id) >= static_cast<unsigned>(symbol_cache_.length())) { if (scanner().is_literal_ascii()) { - return Factory::LookupAsciiSymbol(scanner().literal_ascii_string()); + return isolate()->factory()->LookupAsciiSymbol( + scanner().literal_ascii_string()); } else { - return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string()); + return isolate()->factory()->LookupTwoByteSymbol( + scanner().literal_uc16_string()); } } return LookupCachedSymbol(symbol_id); @@ -360,14 +273,16 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id) { Handle<String> result = symbol_cache_.at(symbol_id); if (result.is_null()) { if (scanner().is_literal_ascii()) { - result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string()); + result = isolate()->factory()->LookupAsciiSymbol( + scanner().literal_ascii_string()); } else { - result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string()); + result = isolate()->factory()->LookupTwoByteSymbol( + scanner().literal_uc16_string()); } symbol_cache_.at(symbol_id) = result; return result; } - Counters::total_preparse_symbols_skipped.Increment(); + isolate()->counters()->total_preparse_symbols_skipped()->Increment(); return result; } @@ -491,7 +406,7 @@ unsigned* ScriptDataImpl::ReadAddress(int position) { Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) { - Scope* result = new Scope(parent, type); + Scope* result = new(zone()) Scope(parent, type); result->Initialize(inside_with); return result; } @@ -544,33 +459,90 @@ class TargetScope BASE_EMBEDDED { // LexicalScope is a support class to facilitate manipulation of the // Parser's scope stack. The constructor sets the parser's top scope // to the incoming scope, and the destructor resets it. +// +// Additionally, it stores transient information used during parsing. +// These scopes are not kept around after parsing or referenced by syntax +// trees so they can be stack-allocated and hence used by the pre-parser. class LexicalScope BASE_EMBEDDED { public: - LexicalScope(Scope** scope_variable, - int* with_nesting_level_variable, - Scope* scope) - : scope_variable_(scope_variable), - with_nesting_level_variable_(with_nesting_level_variable), - prev_scope_(*scope_variable), - prev_level_(*with_nesting_level_variable) { - *scope_variable = scope; - *with_nesting_level_variable = 0; + LexicalScope(Parser* parser, Scope* scope, Isolate* isolate); + ~LexicalScope(); + + int NextMaterializedLiteralIndex() { + int next_index = + materialized_literal_count_ + JSFunction::kLiteralsPrefixSize; + materialized_literal_count_++; + return next_index; } + int materialized_literal_count() { return materialized_literal_count_; } - ~LexicalScope() { - (*scope_variable_)->Leave(); - *scope_variable_ = prev_scope_; - *with_nesting_level_variable_ = prev_level_; + void SetThisPropertyAssignmentInfo( + bool only_simple_this_property_assignments, + Handle<FixedArray> this_property_assignments) { + only_simple_this_property_assignments_ = + only_simple_this_property_assignments; + this_property_assignments_ = this_property_assignments; + } + bool only_simple_this_property_assignments() { + return only_simple_this_property_assignments_; + } + Handle<FixedArray> this_property_assignments() { + return this_property_assignments_; } + void AddProperty() { expected_property_count_++; } + int expected_property_count() { return expected_property_count_; } + private: - Scope** scope_variable_; - int* with_nesting_level_variable_; - Scope* prev_scope_; - int prev_level_; + // Captures the number of literals that need materialization in the + // function. Includes regexp literals, and boilerplate for object + // and array literals. + int materialized_literal_count_; + + // Properties count estimation. + int expected_property_count_; + + // Keeps track of assignments to properties of this. Used for + // optimizing constructors. + bool only_simple_this_property_assignments_; + Handle<FixedArray> this_property_assignments_; + + // Bookkeeping + Parser* parser_; + // Previous values + LexicalScope* lexical_scope_parent_; + Scope* previous_scope_; + int previous_with_nesting_level_; + unsigned previous_ast_node_id_; }; + +LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate) + : materialized_literal_count_(0), + expected_property_count_(0), + only_simple_this_property_assignments_(false), + this_property_assignments_(isolate->factory()->empty_fixed_array()), + parser_(parser), + lexical_scope_parent_(parser->lexical_scope_), + previous_scope_(parser->top_scope_), + previous_with_nesting_level_(parser->with_nesting_level_), + previous_ast_node_id_(isolate->ast_node_id()) { + parser->top_scope_ = scope; + parser->lexical_scope_ = this; + parser->with_nesting_level_ = 0; + isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1); +} + + +LexicalScope::~LexicalScope() { + parser_->top_scope_ = previous_scope_; + parser_->lexical_scope_ = lexical_scope_parent_; + parser_->with_nesting_level_ = previous_with_nesting_level_; + parser_->isolate()->set_ast_node_id(previous_ast_node_id_); +} + + // ---------------------------------------------------------------------------- // The CHECK_OK macro is a convenient macro to enforce error // handling for functions that may fail (by returning !*ok). @@ -598,12 +570,13 @@ Parser::Parser(Handle<Script> script, bool allow_natives_syntax, v8::Extension* extension, ScriptDataImpl* pre_data) - : symbol_cache_(pre_data ? pre_data->symbol_count() : 0), + : isolate_(script->GetIsolate()), + symbol_cache_(pre_data ? pre_data->symbol_count() : 0), script_(script), - scanner_(), + scanner_(isolate_->unicode_cache()), top_scope_(NULL), with_nesting_level_(0), - temp_scope_(NULL), + lexical_scope_(NULL), target_stack_(NULL), allow_natives_syntax_(allow_natives_syntax), extension_(extension), @@ -618,11 +591,11 @@ Parser::Parser(Handle<Script> script, FunctionLiteral* Parser::ParseProgram(Handle<String> source, bool in_global_context, StrictModeFlag strict_mode) { - CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); + ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); - HistogramTimerScope timer(&Counters::parse); - Counters::total_parse_size.Increment(source->length()); - fni_ = new FuncNameInferrer(); + HistogramTimerScope timer(isolate()->counters()->parse()); + isolate()->counters()->total_parse_size()->Increment(source->length()); + fni_ = new(zone()) FuncNameInferrer(isolate()); // Initialize parser state. source->TryFlatten(); @@ -657,40 +630,37 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, in_global_context ? Scope::GLOBAL_SCOPE : Scope::EVAL_SCOPE; - Handle<String> no_name = Factory::empty_symbol(); + Handle<String> no_name = isolate()->factory()->empty_symbol(); FunctionLiteral* result = NULL; { Scope* scope = NewScope(top_scope_, type, inside_with()); - LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, - scope); - TemporaryScope temp_scope(&this->temp_scope_); + LexicalScope lexical_scope(this, scope, isolate()); if (strict_mode == kStrictMode) { - temp_scope.EnableStrictMode(); + top_scope_->EnableStrictMode(); } - ZoneList<Statement*>* body = new ZoneList<Statement*>(16); + ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16); bool ok = true; int beg_loc = scanner().location().beg_pos; ParseSourceElements(body, Token::EOS, &ok); - if (ok && temp_scope_->StrictMode()) { + if (ok && top_scope_->is_strict_mode()) { CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok); } if (ok) { - result = new FunctionLiteral( + result = new(zone()) FunctionLiteral( no_name, top_scope_, body, - temp_scope.materialized_literal_count(), - temp_scope.expected_property_count(), - temp_scope.only_simple_this_property_assignments(), - temp_scope.this_property_assignments(), + lexical_scope.materialized_literal_count(), + lexical_scope.expected_property_count(), + lexical_scope.only_simple_this_property_assignments(), + lexical_scope.this_property_assignments(), 0, 0, source->length(), false, - temp_scope.ContainsLoops(), - temp_scope.StrictMode()); + false); } else if (stack_overflow_) { - Top::StackOverflow(); + isolate()->StackOverflow(); } } @@ -704,10 +674,10 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, } FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) { - CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); - HistogramTimerScope timer(&Counters::parse_lazy); + ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); + HistogramTimerScope timer(isolate()->counters()->parse_lazy()); Handle<String> source(String::cast(script_->source())); - Counters::total_parse_size.Increment(source->length()); + isolate()->counters()->total_parse_size()->Increment(source->length()); Handle<SharedFunctionInfo> shared_info = info->shared_info(); // Initialize parser state. @@ -737,7 +707,7 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, ASSERT(target_stack_ == NULL); Handle<String> name(String::cast(shared_info->name())); - fni_ = new FuncNameInferrer(); + fni_ = new(zone()) FuncNameInferrer(isolate()); fni_->PushEnclosingName(name); mode_ = PARSE_EAGERLY; @@ -747,17 +717,15 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, { // Parse the function literal. - Handle<String> no_name = Factory::empty_symbol(); + Handle<String> no_name = isolate()->factory()->empty_symbol(); Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with()); if (!info->closure().is_null()) { scope = Scope::DeserializeScopeChain(info, scope); } - LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, - scope); - TemporaryScope temp_scope(&this->temp_scope_); + LexicalScope lexical_scope(this, scope, isolate()); if (shared_info->strict_mode()) { - temp_scope.EnableStrictMode(); + top_scope_->EnableStrictMode(); } FunctionLiteralType type = @@ -777,7 +745,7 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, // not safe to do before scope has been deleted. if (result == NULL) { zone_scope->DeleteOnExit(); - if (stack_overflow_) Top::StackOverflow(); + if (stack_overflow_) isolate()->StackOverflow(); } else { Handle<String> inferred_name(shared_info->inferred_name()); result->set_inferred_name(inferred_name); @@ -807,12 +775,15 @@ void Parser::ReportMessageAt(Scanner::Location source_location, MessageLocation location(script_, source_location.beg_pos, source_location.end_pos); - Handle<JSArray> array = Factory::NewJSArray(args.length()); + Factory* factory = isolate()->factory(); + Handle<FixedArray> elements = factory->NewFixedArray(args.length()); for (int i = 0; i < args.length(); i++) { - SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i]))); + Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i])); + elements->set(i, *arg_string); } - Handle<Object> result = Factory::NewSyntaxError(type, array); - Top::Throw(*result, &location); + Handle<JSArray> array = factory->NewJSArrayWithElements(elements); + Handle<Object> result = factory->NewSyntaxError(type, array); + isolate()->Throw(*result, &location); } @@ -822,12 +793,14 @@ void Parser::ReportMessageAt(Scanner::Location source_location, MessageLocation location(script_, source_location.beg_pos, source_location.end_pos); - Handle<JSArray> array = Factory::NewJSArray(args.length()); + Factory* factory = isolate()->factory(); + Handle<FixedArray> elements = factory->NewFixedArray(args.length()); for (int i = 0; i < args.length(); i++) { - SetElement(array, i, args[i]); + elements->set(i, *args[i]); } - Handle<Object> result = Factory::NewSyntaxError(type, array); - Top::Throw(*result, &location); + Handle<JSArray> array = factory->NewJSArrayWithElements(elements); + Handle<Object> result = factory->NewSyntaxError(type, array); + isolate()->Throw(*result, &location); } @@ -952,8 +925,9 @@ class InitializationBlockFinder : public ParserFinder { // function contains only assignments of this type. class ThisNamedPropertyAssigmentFinder : public ParserFinder { public: - ThisNamedPropertyAssigmentFinder() - : only_simple_this_property_assignments_(true), + explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate) + : isolate_(isolate), + only_simple_this_property_assignments_(true), names_(NULL), assigned_arguments_(NULL), assigned_constants_(NULL) {} @@ -984,14 +958,14 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder { // form this.x = y; Handle<FixedArray> GetThisPropertyAssignments() { if (names_ == NULL) { - return Factory::empty_fixed_array(); + return isolate_->factory()->empty_fixed_array(); } ASSERT(names_ != NULL); ASSERT(assigned_arguments_ != NULL); ASSERT_EQ(names_->length(), assigned_arguments_->length()); ASSERT_EQ(names_->length(), assigned_constants_->length()); Handle<FixedArray> assignments = - Factory::NewFixedArray(names_->length() * 3); + isolate_->factory()->NewFixedArray(names_->length() * 3); for (int i = 0; i < names_->length(); i++) { assignments->set(i * 3, *names_->at(i)); assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i))); @@ -1021,7 +995,8 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder { uint32_t dummy; if (literal != NULL && literal->handle()->IsString() && - !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) && + !String::cast(*(literal->handle()))->Equals( + isolate_->heap()->Proto_symbol()) && !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { Handle<String> key = Handle<String>::cast(literal->handle()); @@ -1055,7 +1030,7 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder { EnsureAllocation(); names_->Add(name); assigned_arguments_->Add(index); - assigned_constants_->Add(Factory::undefined_value()); + assigned_constants_->Add(isolate_->factory()->undefined_value()); } void AssignmentFromConstant(Handle<String> name, Handle<Object> value) { @@ -1074,12 +1049,14 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder { if (names_ == NULL) { ASSERT(assigned_arguments_ == NULL); ASSERT(assigned_constants_ == NULL); - names_ = new ZoneStringList(4); - assigned_arguments_ = new ZoneList<int>(4); - assigned_constants_ = new ZoneObjectList(4); + Zone* zone = isolate_->zone(); + names_ = new(zone) ZoneStringList(4); + assigned_arguments_ = new(zone) ZoneList<int>(4); + assigned_constants_ = new(zone) ZoneObjectList(4); } } + Isolate* isolate_; bool only_simple_this_property_assignments_; ZoneStringList* names_; ZoneList<int>* assigned_arguments_; @@ -1101,7 +1078,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, ASSERT(processor != NULL); InitializationBlockFinder block_finder; - ThisNamedPropertyAssigmentFinder this_property_assignment_finder; + ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); bool directive_prologue = true; // Parsing directive prologue. while (peek() != end_token) { @@ -1141,11 +1118,11 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, Handle<String> directive = Handle<String>::cast(literal->handle()); // Check "use strict" directive (ES5 14.1). - if (!temp_scope_->StrictMode() && - directive->Equals(Heap::use_strict()) && + if (!top_scope_->is_strict_mode() && + directive->Equals(isolate()->heap()->use_strict()) && token_loc.end_pos - token_loc.beg_pos == - Heap::use_strict()->length() + 2) { - temp_scope_->EnableStrictMode(); + isolate()->heap()->use_strict()->length() + 2) { + top_scope_->EnableStrictMode(); // "use strict" is the only directive for now. directive_prologue = false; } @@ -1174,7 +1151,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, this_property_assignment_finder.only_simple_this_property_assignments() && top_scope_->declarations()->length() == 0; if (only_simple_this_property_assignments) { - temp_scope_->SetThisPropertyAssignmentInfo( + lexical_scope_->SetThisPropertyAssignmentInfo( only_simple_this_property_assignments, this_property_assignment_finder.GetThisPropertyAssignments()); } @@ -1270,7 +1247,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { // one must take great care not to treat it as a // fall-through. It is much easier just to wrap the entire // try-statement in a statement block and put the labels there - Block* result = new Block(labels, 1, false); + Block* result = new(zone()) Block(labels, 1, false); Target target(&this->target_stack_, result); TryStatement* statement = ParseTryStatement(CHECK_OK); if (statement) { @@ -1283,7 +1260,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { case Token::FUNCTION: { // In strict mode, FunctionDeclaration is only allowed in the context // of SourceElements. - if (temp_scope_->StrictMode()) { + if (top_scope_->is_strict_mode()) { ReportMessageAt(scanner().peek_location(), "strict_function", Vector<const char*>::empty()); *ok = false; @@ -1292,9 +1269,6 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { return ParseFunctionDeclaration(ok); } - case Token::NATIVE: - return ParseNativeDeclaration(ok); - case Token::DEBUGGER: stmt = ParseDebuggerStatement(ok); break; @@ -1325,7 +1299,10 @@ VariableProxy* Parser::Declare(Handle<String> name, // to the corresponding activation frame at runtime if necessary. // For instance declarations inside an eval scope need to be added // to the calling function context. - if (top_scope_->is_function_scope()) { + // Similarly, strict mode eval scope does not leak variable declarations to + // the caller's scope so we declare all locals, too. + if (top_scope_->is_function_scope() || + top_scope_->is_strict_mode_eval_scope()) { // Declare the variable in the function scope. var = top_scope_->LocalLookup(name); if (var == NULL) { @@ -1342,9 +1319,9 @@ VariableProxy* Parser::Declare(Handle<String> name, var->mode() == Variable::CONST); const char* type = (var->mode() == Variable::VAR) ? "var" : "const"; Handle<String> type_string = - Factory::NewStringFromUtf8(CStrVector(type), TENURED); + isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); Expression* expression = - NewThrowTypeError(Factory::redeclaration_symbol(), + NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), type_string, name); top_scope_->SetIllegalRedeclaration(expression); } @@ -1368,13 +1345,13 @@ VariableProxy* Parser::Declare(Handle<String> name, // a performance issue since it may lead to repeated // Runtime::DeclareContextSlot() calls. VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with()); - top_scope_->AddDeclaration(new Declaration(proxy, mode, fun)); + top_scope_->AddDeclaration(new(zone()) Declaration(proxy, mode, fun)); // For global const variables we bind the proxy to a variable. if (mode == Variable::CONST && top_scope_->is_global_scope()) { ASSERT(resolve); // should be set by all callers Variable::Kind kind = Variable::NORMAL; - var = new Variable(top_scope_, name, Variable::CONST, true, kind); + var = new(zone()) Variable(top_scope_, name, Variable::CONST, true, kind); } // If requested and we have a local variable, bind the proxy to the variable @@ -1412,13 +1389,6 @@ VariableProxy* Parser::Declare(Handle<String> name, // declaration is resolved by looking up the function through a // callback provided by the extension. Statement* Parser::ParseNativeDeclaration(bool* ok) { - if (extension_ == NULL) { - ReportUnexpectedToken(Token::NATIVE); - *ok = false; - return NULL; - } - - Expect(Token::NATIVE, CHECK_OK); Expect(Token::FUNCTION, CHECK_OK); Handle<String> name = ParseIdentifier(CHECK_OK); Expect(Token::LPAREN, CHECK_OK); @@ -1450,7 +1420,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { Handle<Code> code = Handle<Code>(fun->shared()->code()); Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); Handle<SharedFunctionInfo> shared = - Factory::NewSharedFunctionInfo(name, literals, code, + isolate()->factory()->NewSharedFunctionInfo(name, literals, code, Handle<SerializedScopeInfo>(fun->shared()->scope_info())); shared->set_construct_stub(*construct_stub); @@ -1462,10 +1432,11 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { // TODO(1240846): It's weird that native function declarations are // introduced dynamically when we meet their declarations, whereas // other functions are setup when entering the surrounding scope. - SharedFunctionInfoLiteral* lit = new SharedFunctionInfoLiteral(shared); + SharedFunctionInfoLiteral* lit = + new(zone()) SharedFunctionInfoLiteral(shared); VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK); - return new ExpressionStatement( - new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)); + return new(zone()) ExpressionStatement(new(zone()) Assignment( + Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)); } @@ -1474,10 +1445,11 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) { // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' Expect(Token::FUNCTION, CHECK_OK); int function_token_position = scanner().location().beg_pos; - bool is_reserved = false; - Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK); + bool is_strict_reserved = false; + Handle<String> name = ParseIdentifierOrStrictReservedWord( + &is_strict_reserved, CHECK_OK); FunctionLiteral* fun = ParseFunctionLiteral(name, - is_reserved, + is_strict_reserved, function_token_position, DECLARATION, CHECK_OK); @@ -1497,7 +1469,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { // (ECMA-262, 3rd, 12.2) // // Construct block expecting 16 statements. - Block* result = new Block(labels, 16, false); + Block* result = new(zone()) Block(labels, 16, false); Target target(&this->target_stack_, result); Expect(Token::LBRACE, CHECK_OK); while (peek() != Token::RBRACE) { @@ -1519,11 +1491,13 @@ Block* Parser::ParseVariableStatement(bool* ok) { return result; } -static bool IsEvalOrArguments(Handle<String> string) { - return string.is_identical_to(Factory::eval_symbol()) || - string.is_identical_to(Factory::arguments_symbol()); + +bool Parser::IsEvalOrArguments(Handle<String> string) { + return string.is_identical_to(isolate()->factory()->eval_symbol()) || + string.is_identical_to(isolate()->factory()->arguments_symbol()); } + // If the variable declaration declares exactly one non-const // variable, then *var is set to that variable. In all other cases, // *var is untouched; in particular, it is the caller's responsibility @@ -1541,7 +1515,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, Consume(Token::VAR); } else if (peek() == Token::CONST) { Consume(Token::CONST); - if (temp_scope_->StrictMode()) { + if (top_scope_->is_strict_mode()) { ReportMessage("strict_const", Vector<const char*>::empty()); *ok = false; return NULL; @@ -1565,7 +1539,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, // is inside an initializer block, it is ignored. // // Create new block with one expected declaration. - Block* block = new Block(NULL, 1, true); + Block* block = new(zone()) Block(NULL, 1, true); VariableProxy* last_var = NULL; // the last variable declared int nvars = 0; // the number of variables declared do { @@ -1577,7 +1551,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, if (fni_ != NULL) fni_->PushVariableName(name); // Strict mode variables may not be named eval or arguments - if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { + if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { ReportMessage("strict_var_name", Vector<const char*>::empty()); *ok = false; return NULL; @@ -1599,6 +1573,12 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, is_const /* always bound for CONST! */, CHECK_OK); nvars++; + if (top_scope_->num_var_or_const() > kMaxNumFunctionLocals) { + ReportMessageAt(scanner().location(), "too_many_variables", + Vector<const char*>::empty()); + *ok = false; + return NULL; + } // Parse initialization expression if present and/or needed. A // declaration of the form: @@ -1634,7 +1614,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, position = scanner().location().beg_pos; value = ParseAssignmentExpression(accept_IN, CHECK_OK); // Don't infer if it is "a = function(){...}();"-like expression. - if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer(); + if (fni_ != NULL && + value->AsCall() == NULL && + value->AsCallNew() == NULL) { + fni_->Infer(); + } } // Make sure that 'const c' actually initializes 'c' to undefined @@ -1665,8 +1649,9 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, if (top_scope_->is_global_scope()) { // Compute the arguments for the runtime call. - ZoneList<Expression*>* arguments = new ZoneList<Expression*>(3); - arguments->Add(new Literal(name)); // we have at least 1 parameter + ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3); + // We have at least 1 parameter. + arguments->Add(new(zone()) Literal(name)); CallRuntime* initialize; if (is_const) { @@ -1678,15 +1663,15 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, // Note that the function does different things depending on // the number of arguments (1 or 2). initialize = - new CallRuntime( - Factory::InitializeConstGlobal_symbol(), + new(zone()) CallRuntime( + isolate()->factory()->InitializeConstGlobal_symbol(), Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments); } else { // Add strict mode. // We may want to pass singleton to avoid Literal allocations. arguments->Add(NewNumberLiteral( - temp_scope_->StrictMode() ? kStrictMode : kNonStrictMode)); + top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode)); // Be careful not to assign a value to the global variable if // we're in a with. The initialization value should not @@ -1702,13 +1687,13 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, // Note that the function does different things depending on // the number of arguments (2 or 3). initialize = - new CallRuntime( - Factory::InitializeVarGlobal_symbol(), + new(zone()) CallRuntime( + isolate()->factory()->InitializeVarGlobal_symbol(), Runtime::FunctionForId(Runtime::kInitializeVarGlobal), arguments); } - block->AddStatement(new ExpressionStatement(initialize)); + block->AddStatement(new(zone()) ExpressionStatement(initialize)); } // Add an assignment node to the initialization statement block if @@ -1723,8 +1708,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, // the top context for variables). Sigh... if (value != NULL) { Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR); - Assignment* assignment = new Assignment(op, last_var, value, position); - if (block) block->AddStatement(new ExpressionStatement(assignment)); + Assignment* assignment = + new(zone()) Assignment(op, last_var, value, position); + if (block) { + block->AddStatement(new(zone()) ExpressionStatement(assignment)); + } } if (fni_ != NULL) fni_->Leave(); @@ -1758,7 +1746,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, // Identifier ':' Statement bool starts_with_idenfifier = peek_any_identifier(); Expression* expr = ParseExpression(true, CHECK_OK); - if (peek() == Token::COLON && starts_with_idenfifier && expr && + if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && expr->AsVariableProxy() != NULL && !expr->AsVariableProxy()->is_this()) { // Expression is a single identifier, and not, e.g., a parenthesized @@ -1778,7 +1766,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, *ok = false; return NULL; } - if (labels == NULL) labels = new ZoneStringList(4); + if (labels == NULL) labels = new(zone()) ZoneStringList(4); labels->Add(label); // Remove the "ghost" variable that turned out to be a label // from the top scope. This way, we don't try to resolve it @@ -1788,9 +1776,23 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, return ParseStatement(labels, ok); } + // If we have an extension, we allow a native function declaration. + // A native function declaration starts with "native function" with + // no line-terminator between the two words. + if (extension_ != NULL && + peek() == Token::FUNCTION && + !scanner().HasAnyLineTerminatorBeforeNext() && + expr != NULL && + expr->AsVariableProxy() != NULL && + expr->AsVariableProxy()->name()->Equals( + isolate()->heap()->native_symbol()) && + !scanner().literal_contains_escapes()) { + return ParseNativeDeclaration(ok); + } + // Parsed expression statement. ExpectSemicolon(CHECK_OK); - return new ExpressionStatement(expr); + return new(zone()) ExpressionStatement(expr); } @@ -1810,7 +1812,7 @@ IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) { } else { else_statement = EmptyStatement(); } - return new IfStatement(condition, then_statement, else_statement); + return new(zone()) IfStatement(condition, then_statement, else_statement); } @@ -1821,7 +1823,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) { Expect(Token::CONTINUE, CHECK_OK); Handle<String> label = Handle<String>::null(); Token::Value tok = peek(); - if (!scanner().has_line_terminator_before_next() && + if (!scanner().HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { label = ParseIdentifier(CHECK_OK); } @@ -1840,7 +1842,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) { return NULL; } ExpectSemicolon(CHECK_OK); - return new ContinueStatement(target); + return new(zone()) ContinueStatement(target); } @@ -1851,7 +1853,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { Expect(Token::BREAK, CHECK_OK); Handle<String> label; Token::Value tok = peek(); - if (!scanner().has_line_terminator_before_next() && + if (!scanner().HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { label = ParseIdentifier(CHECK_OK); } @@ -1875,7 +1877,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { return NULL; } ExpectSemicolon(CHECK_OK); - return new BreakStatement(target); + return new(zone()) BreakStatement(target); } @@ -1894,33 +1896,29 @@ Statement* Parser::ParseReturnStatement(bool* ok) { // // To be consistent with KJS we report the syntax error at runtime. if (!top_scope_->is_function_scope()) { - Handle<String> type = Factory::illegal_return_symbol(); + Handle<String> type = isolate()->factory()->illegal_return_symbol(); Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null()); - return new ExpressionStatement(throw_error); + return new(zone()) ExpressionStatement(throw_error); } Token::Value tok = peek(); - if (scanner().has_line_terminator_before_next() || + if (scanner().HasAnyLineTerminatorBeforeNext() || tok == Token::SEMICOLON || tok == Token::RBRACE || tok == Token::EOS) { ExpectSemicolon(CHECK_OK); - return new ReturnStatement(GetLiteralUndefined()); + return new(zone()) ReturnStatement(GetLiteralUndefined()); } Expression* expr = ParseExpression(true, CHECK_OK); ExpectSemicolon(CHECK_OK); - return new ReturnStatement(expr); + return new(zone()) ReturnStatement(expr); } -Block* Parser::WithHelper(Expression* obj, - ZoneStringList* labels, - bool is_catch_block, - bool* ok) { +Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) { // Parse the statement and collect escaping labels. - ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0); - TargetCollector collector(target_list); + TargetCollector collector; Statement* stat; { Target target(&this->target_stack_, &collector); with_nesting_level_++; @@ -1931,21 +1929,21 @@ Block* Parser::WithHelper(Expression* obj, // Create resulting block with two statements. // 1: Evaluate the with expression. // 2: The try-finally block evaluating the body. - Block* result = new Block(NULL, 2, false); + Block* result = new(zone()) Block(NULL, 2, false); if (result != NULL) { - result->AddStatement(new WithEnterStatement(obj, is_catch_block)); + result->AddStatement(new(zone()) EnterWithContextStatement(obj)); // Create body block. - Block* body = new Block(NULL, 1, false); + Block* body = new(zone()) Block(NULL, 1, false); body->AddStatement(stat); // Create exit block. - Block* exit = new Block(NULL, 1, false); - exit->AddStatement(new WithExitStatement()); + Block* exit = new(zone()) Block(NULL, 1, false); + exit->AddStatement(new(zone()) ExitContextStatement()); // Return a try-finally statement. - TryFinallyStatement* wrapper = new TryFinallyStatement(body, exit); + TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit); wrapper->set_escaping_targets(collector.targets()); result->AddStatement(wrapper); } @@ -1959,7 +1957,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { Expect(Token::WITH, CHECK_OK); - if (temp_scope_->StrictMode()) { + if (top_scope_->is_strict_mode()) { ReportMessage("strict_mode_with", Vector<const char*>::empty()); *ok = false; return NULL; @@ -1969,7 +1967,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { Expression* expr = ParseExpression(true, CHECK_OK); Expect(Token::RPAREN, CHECK_OK); - return WithHelper(expr, labels, false, CHECK_OK); + return WithHelper(expr, labels, CHECK_OK); } @@ -1994,7 +1992,7 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { } Expect(Token::COLON, CHECK_OK); int pos = scanner().location().beg_pos; - ZoneList<Statement*>* statements = new ZoneList<Statement*>(5); + ZoneList<Statement*>* statements = new(zone()) ZoneList<Statement*>(5); while (peek() != Token::CASE && peek() != Token::DEFAULT && peek() != Token::RBRACE) { @@ -2002,7 +2000,7 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { statements->Add(stat); } - return new CaseClause(label, statements, pos); + return new(zone()) CaseClause(label, statements, pos); } @@ -2011,7 +2009,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels, // SwitchStatement :: // 'switch' '(' Expression ')' '{' CaseClause* '}' - SwitchStatement* statement = new SwitchStatement(labels); + SwitchStatement* statement = new(zone()) SwitchStatement(labels); Target target(&this->target_stack_, statement); Expect(Token::SWITCH, CHECK_OK); @@ -2020,7 +2018,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels, Expect(Token::RPAREN, CHECK_OK); bool default_seen = false; - ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4); + ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4); Expect(Token::LBRACE, CHECK_OK); while (peek() != Token::RBRACE) { CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK); @@ -2039,7 +2037,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) { Expect(Token::THROW, CHECK_OK); int pos = scanner().location().beg_pos; - if (scanner().has_line_terminator_before_next()) { + if (scanner().HasAnyLineTerminatorBeforeNext()) { ReportMessage("newline_after_throw", Vector<const char*>::empty()); *ok = false; return NULL; @@ -2047,7 +2045,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) { Expression* exception = ParseExpression(true, CHECK_OK); ExpectSemicolon(CHECK_OK); - return new ExpressionStatement(new Throw(exception, pos)); + return new(zone()) ExpressionStatement(new(zone()) Throw(exception, pos)); } @@ -2065,18 +2063,13 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { Expect(Token::TRY, CHECK_OK); - ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0); - TargetCollector collector(target_list); + TargetCollector try_collector; Block* try_block; - { Target target(&this->target_stack_, &collector); + { Target target(&this->target_stack_, &try_collector); try_block = ParseBlock(NULL, CHECK_OK); } - Block* catch_block = NULL; - Variable* catch_var = NULL; - Block* finally_block = NULL; - Token::Value tok = peek(); if (tok != Token::CATCH && tok != Token::FINALLY) { ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); @@ -2085,20 +2078,19 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { } // If we can break out from the catch block and there is a finally block, - // then we will need to collect jump targets from the catch block. Since - // we don't know yet if there will be a finally block, we always collect - // the jump targets. - ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); - TargetCollector catch_collector(catch_target_list); - bool has_catch = false; + // then we will need to collect escaping targets from the catch + // block. Since we don't know yet if there will be a finally block, we + // always collect the targets. + TargetCollector catch_collector; + Block* catch_block = NULL; + Handle<String> name; if (tok == Token::CATCH) { - has_catch = true; Consume(Token::CATCH); Expect(Token::LPAREN, CHECK_OK); - Handle<String> name = ParseIdentifier(CHECK_OK); + name = ParseIdentifier(CHECK_OK); - if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { + if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { ReportMessage("strict_catch_variable", Vector<const char*>::empty()); *ok = false; return NULL; @@ -2107,15 +2099,33 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { Expect(Token::RPAREN, CHECK_OK); if (peek() == Token::LBRACE) { - // Allocate a temporary for holding the finally state while - // executing the finally block. - catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol()); - Literal* name_literal = new Literal(name); - VariableProxy* catch_var_use = new VariableProxy(catch_var); - Expression* obj = new CatchExtensionObject(name_literal, catch_var_use); + // Rewrite the catch body B to a single statement block + // { try B finally { PopContext }}. + Block* inner_body; + // We need to collect escapes from the body for both the inner + // try/finally used to pop the catch context and any possible outer + // try/finally. + TargetCollector inner_collector; { Target target(&this->target_stack_, &catch_collector); - catch_block = WithHelper(obj, NULL, true, CHECK_OK); + { Target target(&this->target_stack_, &inner_collector); + ++with_nesting_level_; + top_scope_->RecordWithStatement(); + inner_body = ParseBlock(NULL, CHECK_OK); + --with_nesting_level_; + } } + + // Create exit block. + Block* inner_finally = new(zone()) Block(NULL, 1, false); + inner_finally->AddStatement(new(zone()) ExitContextStatement()); + + // Create a try/finally statement. + TryFinallyStatement* inner_try_finally = + new(zone()) TryFinallyStatement(inner_body, inner_finally); + inner_try_finally->set_escaping_targets(inner_collector.targets()); + + catch_block = new(zone()) Block(NULL, 1, false); + catch_block->AddStatement(inner_try_finally); } else { Expect(Token::LBRACE, CHECK_OK); } @@ -2123,24 +2133,22 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { tok = peek(); } - if (tok == Token::FINALLY || !has_catch) { + Block* finally_block = NULL; + if (tok == Token::FINALLY || catch_block == NULL) { Consume(Token::FINALLY); - // Declare a variable for holding the finally state while - // executing the finally block. finally_block = ParseBlock(NULL, CHECK_OK); } // Simplify the AST nodes by converting: - // 'try { } catch { } finally { }' + // 'try B0 catch B1 finally B2' // to: - // 'try { try { } catch { } } finally { }' + // 'try { try B0 catch B1 } finally B2' if (catch_block != NULL && finally_block != NULL) { - VariableProxy* catch_var_defn = new VariableProxy(catch_var); TryCatchStatement* statement = - new TryCatchStatement(try_block, catch_var_defn, catch_block); - statement->set_escaping_targets(collector.targets()); - try_block = new Block(NULL, 1, false); + new(zone()) TryCatchStatement(try_block, name, catch_block); + statement->set_escaping_targets(try_collector.targets()); + try_block = new(zone()) Block(NULL, 1, false); try_block->AddStatement(statement); catch_block = NULL; } @@ -2148,19 +2156,16 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { TryStatement* result = NULL; if (catch_block != NULL) { ASSERT(finally_block == NULL); - VariableProxy* catch_var_defn = new VariableProxy(catch_var); - result = new TryCatchStatement(try_block, catch_var_defn, catch_block); - result->set_escaping_targets(collector.targets()); + result = + new(zone()) TryCatchStatement(try_block, name, catch_block); } else { ASSERT(finally_block != NULL); - result = new TryFinallyStatement(try_block, finally_block); - // Add the jump targets of the try block and the catch block. - for (int i = 0; i < collector.targets()->length(); i++) { - catch_collector.AddTarget(collector.targets()->at(i)); - } - result->set_escaping_targets(catch_collector.targets()); + result = new(zone()) TryFinallyStatement(try_block, finally_block); + // Combine the jump targets of the try block and the possible catch block. + try_collector.targets()->AddAll(*catch_collector.targets()); } + result->set_escaping_targets(try_collector.targets()); return result; } @@ -2170,8 +2175,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, // DoStatement :: // 'do' Statement 'while' '(' Expression ')' ';' - temp_scope_->AddLoop(); - DoWhileStatement* loop = new DoWhileStatement(labels); + DoWhileStatement* loop = new(zone()) DoWhileStatement(labels); Target target(&this->target_stack_, loop); Expect(Token::DO, CHECK_OK); @@ -2185,7 +2189,6 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, } Expression* cond = ParseExpression(true, CHECK_OK); - if (cond != NULL) cond->set_is_loop_condition(true); Expect(Token::RPAREN, CHECK_OK); // Allow do-statements to be terminated with and without @@ -2203,14 +2206,12 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { // WhileStatement :: // 'while' '(' Expression ')' Statement - temp_scope_->AddLoop(); - WhileStatement* loop = new WhileStatement(labels); + WhileStatement* loop = new(zone()) WhileStatement(labels); Target target(&this->target_stack_, loop); Expect(Token::WHILE, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); Expression* cond = ParseExpression(true, CHECK_OK); - if (cond != NULL) cond->set_is_loop_condition(true); Expect(Token::RPAREN, CHECK_OK); Statement* body = ParseStatement(NULL, CHECK_OK); @@ -2223,7 +2224,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { // ForStatement :: // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement - temp_scope_->AddLoop(); Statement* init = NULL; Expect(Token::FOR, CHECK_OK); @@ -2234,7 +2234,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { Block* variable_statement = ParseVariableDeclarations(false, &each, CHECK_OK); if (peek() == Token::IN && each != NULL) { - ForInStatement* loop = new ForInStatement(labels); + ForInStatement* loop = new(zone()) ForInStatement(labels); Target target(&this->target_stack_, loop); Expect(Token::IN, CHECK_OK); @@ -2243,7 +2243,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { Statement* body = ParseStatement(NULL, CHECK_OK); loop->Initialize(each, enumerable, body); - Block* result = new Block(NULL, 2, false); + Block* result = new(zone()) Block(NULL, 2, false); result->AddStatement(variable_statement); result->AddStatement(loop); // Parsed for-in loop w/ variable/const declaration. @@ -2260,10 +2260,11 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { // error here but for compatibility with JSC we choose to report // the error at runtime. if (expression == NULL || !expression->IsValidLeftHandSide()) { - Handle<String> type = Factory::invalid_lhs_in_for_in_symbol(); + Handle<String> type = + isolate()->factory()->invalid_lhs_in_for_in_symbol(); expression = NewThrowReferenceError(type); } - ForInStatement* loop = new ForInStatement(labels); + ForInStatement* loop = new(zone()) ForInStatement(labels); Target target(&this->target_stack_, loop); Expect(Token::IN, CHECK_OK); @@ -2276,13 +2277,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { return loop; } else { - init = new ExpressionStatement(expression); + init = new(zone()) ExpressionStatement(expression); } } } // Standard 'for' loop - ForStatement* loop = new ForStatement(labels); + ForStatement* loop = new(zone()) ForStatement(labels); Target target(&this->target_stack_, loop); // Parsed initializer at this point. @@ -2291,14 +2292,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { Expression* cond = NULL; if (peek() != Token::SEMICOLON) { cond = ParseExpression(true, CHECK_OK); - if (cond != NULL) cond->set_is_loop_condition(true); } Expect(Token::SEMICOLON, CHECK_OK); Statement* next = NULL; if (peek() != Token::RPAREN) { Expression* exp = ParseExpression(true, CHECK_OK); - next = new ExpressionStatement(exp); + next = new(zone()) ExpressionStatement(exp); } Expect(Token::RPAREN, CHECK_OK); @@ -2319,7 +2319,7 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { Expect(Token::COMMA, CHECK_OK); int position = scanner().location().beg_pos; Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK); - result = new BinaryOperation(Token::COMMA, result, right, position); + result = new(zone()) BinaryOperation(Token::COMMA, result, right, position); } return result; } @@ -2345,11 +2345,12 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { // for compatibility with JSC we choose to report the error at // runtime. if (expression == NULL || !expression->IsValidLeftHandSide()) { - Handle<String> type = Factory::invalid_lhs_in_assignment_symbol(); + Handle<String> type = + isolate()->factory()->invalid_lhs_in_assignment_symbol(); expression = NewThrowReferenceError(type); } - if (temp_scope_->StrictMode()) { + if (top_scope_->is_strict_mode()) { // Assignment to eval or arguments is disallowed in strict mode. CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK); } @@ -2368,7 +2369,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { property != NULL && property->obj()->AsVariableProxy() != NULL && property->obj()->AsVariableProxy()->is_this()) { - temp_scope_->AddProperty(); + lexical_scope_->AddProperty(); } // If we assign a function literal to a property we pretenure the @@ -2384,13 +2385,13 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { if ((op == Token::INIT_VAR || op == Token::INIT_CONST || op == Token::ASSIGN) - && (right->AsCall() == NULL)) { + && (right->AsCall() == NULL && right->AsCallNew() == NULL)) { fni_->Infer(); } fni_->Leave(); } - return new Assignment(op, expression, right, pos); + return new(zone()) Assignment(op, expression, right, pos); } @@ -2412,7 +2413,7 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) { Expect(Token::COLON, CHECK_OK); int right_position = scanner().peek_location().beg_pos; Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK); - return new Conditional(expression, left, right, + return new(zone()) Conditional(expression, left, right, left_position, right_position); } @@ -2500,12 +2501,12 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { x = NewCompareNode(cmp, x, y, position); if (cmp != op) { // The comparison was negated - add a NOT. - x = new UnaryOperation(Token::NOT, x); + x = new(zone()) UnaryOperation(Token::NOT, x, position); } } else { // We have a "normal" binary operation. - x = new BinaryOperation(op, x, y, position); + x = new(zone()) BinaryOperation(op, x, y, position); } } } @@ -2522,15 +2523,15 @@ Expression* Parser::NewCompareNode(Token::Value op, bool is_strict = (op == Token::EQ_STRICT); Literal* x_literal = x->AsLiteral(); if (x_literal != NULL && x_literal->IsNull()) { - return new CompareToNull(is_strict, y); + return new(zone()) CompareToNull(is_strict, y); } Literal* y_literal = y->AsLiteral(); if (y_literal != NULL && y_literal->IsNull()) { - return new CompareToNull(is_strict, x); + return new(zone()) CompareToNull(is_strict, x); } } - return new CompareOperation(op, x, y, position); + return new(zone()) CompareOperation(op, x, y, position); } @@ -2550,25 +2551,34 @@ Expression* Parser::ParseUnaryExpression(bool* ok) { Token::Value op = peek(); if (Token::IsUnaryOp(op)) { op = Next(); + int position = scanner().location().beg_pos; Expression* expression = ParseUnaryExpression(CHECK_OK); - // Compute some expressions involving only number literals. - if (expression != NULL && expression->AsLiteral() && - expression->AsLiteral()->handle()->IsNumber()) { - double value = expression->AsLiteral()->handle()->Number(); - switch (op) { - case Token::ADD: - return expression; - case Token::SUB: - return NewNumberLiteral(-value); - case Token::BIT_NOT: - return NewNumberLiteral(~DoubleToInt32(value)); - default: break; + if (expression != NULL && (expression->AsLiteral() != NULL)) { + Handle<Object> literal = expression->AsLiteral()->handle(); + if (op == Token::NOT) { + // Convert the literal to a boolean condition and negate it. + bool condition = literal->ToBoolean()->IsTrue(); + Handle<Object> result(isolate()->heap()->ToBoolean(!condition)); + return new(zone()) Literal(result); + } else if (literal->IsNumber()) { + // Compute some expressions involving only number literals. + double value = literal->Number(); + switch (op) { + case Token::ADD: + return expression; + case Token::SUB: + return NewNumberLiteral(-value); + case Token::BIT_NOT: + return NewNumberLiteral(~DoubleToInt32(value)); + default: + break; + } } } // "delete identifier" is a syntax error in strict mode. - if (op == Token::DELETE && temp_scope_->StrictMode()) { + if (op == Token::DELETE && top_scope_->is_strict_mode()) { VariableProxy* operand = expression->AsVariableProxy(); if (operand != NULL && !operand->is_this()) { ReportMessage("strict_delete", Vector<const char*>::empty()); @@ -2577,7 +2587,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) { } } - return new UnaryOperation(op, expression); + return new(zone()) UnaryOperation(op, expression, position); } else if (Token::IsCountOp(op)) { op = Next(); @@ -2587,18 +2597,21 @@ Expression* Parser::ParseUnaryExpression(bool* ok) { // error here but for compatibility with JSC we choose to report the // error at runtime. if (expression == NULL || !expression->IsValidLeftHandSide()) { - Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol(); + Handle<String> type = + isolate()->factory()->invalid_lhs_in_prefix_op_symbol(); expression = NewThrowReferenceError(type); } - if (temp_scope_->StrictMode()) { + if (top_scope_->is_strict_mode()) { // Prefix expression operand in strict mode may not be eval or arguments. CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); } int position = scanner().location().beg_pos; - IncrementOperation* increment = new IncrementOperation(op, expression); - return new CountOperation(true /* prefix */, increment, position); + return new(zone()) CountOperation(op, + true /* prefix */, + expression, + position); } else { return ParsePostfixExpression(ok); @@ -2611,26 +2624,30 @@ Expression* Parser::ParsePostfixExpression(bool* ok) { // LeftHandSideExpression ('++' | '--')? Expression* expression = ParseLeftHandSideExpression(CHECK_OK); - if (!scanner().has_line_terminator_before_next() && + if (!scanner().HasAnyLineTerminatorBeforeNext() && Token::IsCountOp(peek())) { // Signal a reference error if the expression is an invalid // left-hand side expression. We could report this as a syntax // error here but for compatibility with JSC we choose to report the // error at runtime. if (expression == NULL || !expression->IsValidLeftHandSide()) { - Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol(); + Handle<String> type = + isolate()->factory()->invalid_lhs_in_postfix_op_symbol(); expression = NewThrowReferenceError(type); } - if (temp_scope_->StrictMode()) { + if (top_scope_->is_strict_mode()) { // Postfix expression operand in strict mode may not be eval or arguments. CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); } Token::Value next = Next(); int position = scanner().location().beg_pos; - IncrementOperation* increment = new IncrementOperation(next, expression); - expression = new CountOperation(false /* postfix */, increment, position); + expression = + new(zone()) CountOperation(next, + false /* postfix */, + expression, + position); } return expression; } @@ -2653,7 +2670,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) { Consume(Token::LBRACK); int pos = scanner().location().beg_pos; Expression* index = ParseExpression(true, CHECK_OK); - result = new Property(result, index, pos); + result = new(zone()) Property(result, index, pos); Expect(Token::RBRACK, CHECK_OK); break; } @@ -2675,7 +2692,8 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) { // is called without a receiver and it refers to the original eval // function. VariableProxy* callee = result->AsVariableProxy(); - if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) { + if (callee != NULL && + callee->IsVariable(isolate()->factory()->eval_symbol())) { Handle<String> name = callee->name(); Variable* var = top_scope_->Lookup(name); if (var == NULL) { @@ -2690,7 +2708,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) { Consume(Token::PERIOD); int pos = scanner().location().beg_pos; Handle<String> name = ParseIdentifierName(CHECK_OK); - result = new Property(result, new Literal(name), pos); + result = new(zone()) Property(result, new(zone()) Literal(name), pos); if (fni_ != NULL) fni_->PushLiteralName(name); break; } @@ -2726,7 +2744,9 @@ Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) { if (!stack->is_empty()) { int last = stack->pop(); - result = new CallNew(result, new ZoneList<Expression*>(0), last); + result = new(zone()) CallNew(result, + new(zone()) ZoneList<Expression*>(0), + last); } return result; } @@ -2755,11 +2775,12 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, Expect(Token::FUNCTION, CHECK_OK); int function_token_position = scanner().location().beg_pos; Handle<String> name; - bool is_reserved_name = false; + bool is_strict_reserved_name = false; if (peek_any_identifier()) { - name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK); + name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, + CHECK_OK); } - result = ParseFunctionLiteral(name, is_reserved_name, + result = ParseFunctionLiteral(name, is_strict_reserved_name, function_token_position, NESTED, CHECK_OK); } else { result = ParsePrimaryExpression(CHECK_OK); @@ -2771,7 +2792,15 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, Consume(Token::LBRACK); int pos = scanner().location().beg_pos; Expression* index = ParseExpression(true, CHECK_OK); - result = new Property(result, index, pos); + result = new(zone()) Property(result, index, pos); + if (fni_ != NULL) { + if (index->IsPropertyName()) { + fni_->PushLiteralName(index->AsLiteral()->AsPropertyName()); + } else { + fni_->PushLiteralName( + isolate()->factory()->anonymous_function_symbol()); + } + } Expect(Token::RBRACK, CHECK_OK); break; } @@ -2779,7 +2808,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, Consume(Token::PERIOD); int pos = scanner().location().beg_pos; Handle<String> name = ParseIdentifierName(CHECK_OK); - result = new Property(result, new Literal(name), pos); + result = new(zone()) Property(result, new(zone()) Literal(name), pos); if (fni_ != NULL) fni_->PushLiteralName(name); break; } @@ -2807,7 +2836,7 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { Expect(Token::DEBUGGER, CHECK_OK); ExpectSemicolon(CHECK_OK); - return new DebuggerStatement(); + return new(zone()) DebuggerStatement(); } @@ -2830,7 +2859,10 @@ void Parser::ReportUnexpectedToken(Token::Value token) { return ReportMessage("unexpected_token_identifier", Vector<const char*>::empty()); case Token::FUTURE_RESERVED_WORD: - return ReportMessage(temp_scope_->StrictMode() ? + return ReportMessage("unexpected_reserved", + Vector<const char*>::empty()); + case Token::FUTURE_STRICT_RESERVED_WORD: + return ReportMessage(top_scope_->is_strict_mode() ? "unexpected_strict_reserved" : "unexpected_token_identifier", Vector<const char*>::empty()); @@ -2876,31 +2908,34 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { case Token::NULL_LITERAL: Consume(Token::NULL_LITERAL); - result = new Literal(Factory::null_value()); + result = new(zone()) Literal(isolate()->factory()->null_value()); break; case Token::TRUE_LITERAL: Consume(Token::TRUE_LITERAL); - result = new Literal(Factory::true_value()); + result = new(zone()) Literal(isolate()->factory()->true_value()); break; case Token::FALSE_LITERAL: Consume(Token::FALSE_LITERAL); - result = new Literal(Factory::false_value()); + result = new(zone()) Literal(isolate()->factory()->false_value()); break; case Token::IDENTIFIER: - case Token::FUTURE_RESERVED_WORD: { + case Token::FUTURE_STRICT_RESERVED_WORD: { Handle<String> name = ParseIdentifier(CHECK_OK); if (fni_ != NULL) fni_->PushVariableName(name); - result = top_scope_->NewUnresolved(name, inside_with()); + result = top_scope_->NewUnresolved(name, + inside_with(), + scanner().location().beg_pos); break; } case Token::NUMBER: { Consume(Token::NUMBER); ASSERT(scanner().is_literal_ascii()); - double value = StringToDouble(scanner().literal_ascii_string(), + double value = StringToDouble(isolate()->unicode_cache(), + scanner().literal_ascii_string(), ALLOW_HEX | ALLOW_OCTALS); result = NewNumberLiteral(value); break; @@ -2909,7 +2944,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { case Token::STRING: { Consume(Token::STRING); Handle<String> symbol = GetSymbol(CHECK_OK); - result = new Literal(symbol); + result = new(zone()) Literal(symbol); if (fni_ != NULL) fni_->PushLiteralName(symbol); break; } @@ -2990,7 +3025,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) { // ArrayLiteral :: // '[' Expression? (',' Expression?)* ']' - ZoneList<Expression*>* values = new ZoneList<Expression*>(4); + ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4); Expect(Token::LBRACK, CHECK_OK); while (peek() != Token::RBRACK) { Expression* elem; @@ -3007,11 +3042,11 @@ Expression* Parser::ParseArrayLiteral(bool* ok) { Expect(Token::RBRACK, CHECK_OK); // Update the scope information before the pre-parsing bailout. - int literal_index = temp_scope_->NextMaterializedLiteralIndex(); + int literal_index = lexical_scope_->NextMaterializedLiteralIndex(); // Allocate a fixed array with all the literals. Handle<FixedArray> literals = - Factory::NewFixedArray(values->length(), TENURED); + isolate()->factory()->NewFixedArray(values->length(), TENURED); // Fill in the literals. bool is_simple = true; @@ -3033,10 +3068,10 @@ Expression* Parser::ParseArrayLiteral(bool* ok) { // Simple and shallow arrays can be lazily copied, we transform the // elements array to a copy-on-write array. if (is_simple && depth == 1 && values->length() > 0) { - literals->set_map(Heap::fixed_cow_array_map()); + literals->set_map(isolate()->heap()->fixed_cow_array_map()); } - return new ArrayLiteral(literals, values, + return new(zone()) ArrayLiteral(literals, values, literal_index, is_simple, depth); } @@ -3068,7 +3103,7 @@ bool CompileTimeValue::ArrayLiteralElementNeedsInitialization( Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) { ASSERT(IsCompileTimeValue(expression)); - Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED); + Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED); ObjectLiteral* object_literal = expression->AsObjectLiteral(); if (object_literal != NULL) { ASSERT(object_literal->is_simple()); @@ -3106,7 +3141,7 @@ Handle<Object> Parser::GetBoilerplateValue(Expression* expression) { if (CompileTimeValue::IsCompileTimeValue(expression)) { return CompileTimeValue::GetValue(expression); } - return Factory::undefined_value(); + return isolate()->factory()->undefined_value(); } // Defined in ast.cc @@ -3172,7 +3207,7 @@ void ObjectLiteralPropertyChecker::CheckProperty( if (handle->IsSymbol()) { Handle<String> name(String::cast(*handle)); if (name->AsArrayIndex(&hash)) { - Handle<Object> key_handle = Factory::NewNumberFromUint(hash); + Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash); key = key_handle.location(); map = &elems; } else { @@ -3189,7 +3224,7 @@ void ObjectLiteralPropertyChecker::CheckProperty( char arr[100]; Vector<char> buffer(arr, ARRAY_SIZE(arr)); const char* str = DoubleToCString(num, buffer); - Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); + Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str)); key = name.location(); hash = name->Hash(); map = &props; @@ -3298,10 +3333,11 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, bool is_keyword = Token::IsKeyword(next); if (next == Token::IDENTIFIER || next == Token::NUMBER || next == Token::FUTURE_RESERVED_WORD || + next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::STRING || is_keyword) { Handle<String> name; if (is_keyword) { - name = Factory::LookupAsciiSymbol(Token::String(next)); + name = isolate_->factory()->LookupAsciiSymbol(Token::String(next)); } else { name = GetSymbol(CHECK_OK); } @@ -3314,7 +3350,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, // Allow any number of parameters for compatiabilty with JSC. // Specification only allows zero parameters for get and one for set. ObjectLiteral::Property* property = - new ObjectLiteral::Property(is_getter, value); + new(zone()) ObjectLiteral::Property(is_getter, value); return property; } else { ReportUnexpectedToken(next); @@ -3332,10 +3368,11 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { // )*[','] '}' ZoneList<ObjectLiteral::Property*>* properties = - new ZoneList<ObjectLiteral::Property*>(4); + new(zone()) ZoneList<ObjectLiteral::Property*>(4); int number_of_boilerplate_properties = 0; + bool has_function = false; - ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode()); + ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode()); Expect(Token::LBRACE, CHECK_OK); Scanner::Location loc = scanner().location(); @@ -3351,11 +3388,12 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { switch (next) { case Token::FUTURE_RESERVED_WORD: + case Token::FUTURE_STRICT_RESERVED_WORD: case Token::IDENTIFIER: { bool is_getter = false; bool is_setter = false; Handle<String> id = - ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); + ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); if (fni_ != NULL) fni_->PushLiteralName(id); if ((is_getter || is_setter) && peek() != Token::COLON) { @@ -3379,7 +3417,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { } // Failed to parse as get/set property, so it's just a property // called "get" or "set". - key = new Literal(id); + key = new(zone()) Literal(id); break; } case Token::STRING: { @@ -3391,13 +3429,14 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { key = NewNumberLiteral(index); break; } - key = new Literal(string); + key = new(zone()) Literal(string); break; } case Token::NUMBER: { Consume(Token::NUMBER); ASSERT(scanner().is_literal_ascii()); - double value = StringToDouble(scanner().literal_ascii_string(), + double value = StringToDouble(isolate()->unicode_cache(), + scanner().literal_ascii_string(), ALLOW_HEX | ALLOW_OCTALS); key = NewNumberLiteral(value); break; @@ -3406,7 +3445,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { if (Token::IsKeyword(next)) { Consume(next); Handle<String> string = GetSymbol(CHECK_OK); - key = new Literal(string); + key = new(zone()) Literal(string); } else { // Unexpected token. Token::Value next = Next(); @@ -3420,7 +3459,14 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { Expression* value = ParseAssignmentExpression(true, CHECK_OK); ObjectLiteral::Property* property = - new ObjectLiteral::Property(key, value); + new(zone()) ObjectLiteral::Property(key, value); + + // Mark object literals that contain function literals and pretenure the + // literal so it can be added as a constant function property. + if (value->AsFunctionLiteral() != NULL) { + has_function = true; + value->AsFunctionLiteral()->set_pretenure(true); + } // Count CONSTANT or COMPUTED properties to maintain the enumeration order. if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; @@ -3439,10 +3485,10 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { Expect(Token::RBRACE, CHECK_OK); // Computation of literal_index must happen before pre parse bailout. - int literal_index = temp_scope_->NextMaterializedLiteralIndex(); + int literal_index = lexical_scope_->NextMaterializedLiteralIndex(); - Handle<FixedArray> constant_properties = - Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); + Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray( + number_of_boilerplate_properties * 2, TENURED); bool is_simple = true; bool fast_elements = true; @@ -3452,12 +3498,13 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { &is_simple, &fast_elements, &depth); - return new ObjectLiteral(constant_properties, + return new(zone()) ObjectLiteral(constant_properties, properties, literal_index, is_simple, fast_elements, - depth); + depth, + has_function); } @@ -3469,14 +3516,14 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { return NULL; } - int literal_index = temp_scope_->NextMaterializedLiteralIndex(); + int literal_index = lexical_scope_->NextMaterializedLiteralIndex(); Handle<String> js_pattern = NextLiteralString(TENURED); scanner().ScanRegExpFlags(); Handle<String> js_flags = NextLiteralString(TENURED); Next(); - return new RegExpLiteral(js_pattern, js_flags, literal_index); + return new(zone()) RegExpLiteral(js_pattern, js_flags, literal_index); } @@ -3484,7 +3531,7 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { // Arguments :: // '(' (AssignmentExpression)*[','] ')' - ZoneList<Expression*>* result = new ZoneList<Expression*>(4); + ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4); Expect(Token::LPAREN, CHECK_OK); bool done = (peek() == Token::RPAREN); while (!done) { @@ -3505,7 +3552,7 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, - bool name_is_reserved, + bool name_is_strict_reserved, int function_token_position, FunctionLiteralType type, bool* ok) { @@ -3517,49 +3564,56 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, // this is the actual function name, otherwise this is the name of the // variable declared and initialized with the function (expression). In // that case, we don't have a function name (it's empty). - Handle<String> name = is_named ? var_name : Factory::empty_symbol(); + Handle<String> name = + is_named ? var_name : isolate()->factory()->empty_symbol(); // The function name, if any. - Handle<String> function_name = Factory::empty_symbol(); + Handle<String> function_name = isolate()->factory()->empty_symbol(); if (is_named && (type == EXPRESSION || type == NESTED)) { function_name = name; } int num_parameters = 0; + Scope* scope = NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); + ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8); + int materialized_literal_count; + int expected_property_count; + int start_pos; + int end_pos; + bool only_simple_this_property_assignments; + Handle<FixedArray> this_property_assignments; + bool has_duplicate_parameters = false; // Parse function body. - { Scope* scope = - NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); - LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, - scope); - TemporaryScope temp_scope(&this->temp_scope_); + { LexicalScope lexical_scope(this, scope, isolate()); top_scope_->SetScopeName(name); // FormalParameterList :: // '(' (Identifier)*[','] ')' Expect(Token::LPAREN, CHECK_OK); - int start_pos = scanner().location().beg_pos; - Scanner::Location name_loc = Scanner::NoLocation(); - Scanner::Location dupe_loc = Scanner::NoLocation(); - Scanner::Location reserved_loc = Scanner::NoLocation(); + start_pos = scanner().location().beg_pos; + Scanner::Location name_loc = Scanner::Location::invalid(); + Scanner::Location dupe_loc = Scanner::Location::invalid(); + Scanner::Location reserved_loc = Scanner::Location::invalid(); bool done = (peek() == Token::RPAREN); while (!done) { - bool is_reserved = false; + bool is_strict_reserved = false; Handle<String> param_name = - ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK); + ParseIdentifierOrStrictReservedWord(&is_strict_reserved, + CHECK_OK); // Store locations for possible future error reports. if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) { name_loc = scanner().location(); } if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) { + has_duplicate_parameters = true; dupe_loc = scanner().location(); } - if (!reserved_loc.IsValid() && is_reserved) { + if (!reserved_loc.IsValid() && is_strict_reserved) { reserved_loc = scanner().location(); } - Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR); - top_scope_->AddParameter(parameter); + top_scope_->DeclareParameter(param_name); num_parameters++; if (num_parameters > kMaxNumFunctionParameters) { ReportMessageAt(scanner().location(), "too_many_parameters", @@ -3573,7 +3627,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, Expect(Token::RPAREN, CHECK_OK); Expect(Token::LBRACE, CHECK_OK); - ZoneList<Statement*>* body = new ZoneList<Statement*>(8); // If we have a named function expression, we add a local variable // declaration to the body of the function with the name of the @@ -3586,9 +3639,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, VariableProxy* fproxy = top_scope_->NewUnresolved(function_name, inside_with()); fproxy->BindTo(fvar); - body->Add(new ExpressionStatement( - new Assignment(Token::INIT_CONST, fproxy, - new ThisFunction(), + body->Add(new(zone()) ExpressionStatement( + new(zone()) Assignment(Token::INIT_CONST, fproxy, + new(zone()) ThisFunction(), RelocInfo::kNoPosition))); } @@ -3601,11 +3654,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, parenthesized_function_ = false; // The bit was set for this function only. int function_block_pos = scanner().location().beg_pos; - int materialized_literal_count; - int expected_property_count; - int end_pos; - bool only_simple_this_property_assignments; - Handle<FixedArray> this_property_assignments; if (is_lazily_compiled && pre_data() != NULL) { FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); if (!entry.is_valid()) { @@ -3616,29 +3664,31 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, // End position greater than end of stream is safe, and hard to check. ReportInvalidPreparseData(name, CHECK_OK); } - Counters::total_preparse_skipped.Increment(end_pos - function_block_pos); + isolate()->counters()->total_preparse_skipped()->Increment( + end_pos - function_block_pos); // Seek to position just before terminal '}'. scanner().SeekForward(end_pos - 1); materialized_literal_count = entry.literal_count(); expected_property_count = entry.property_count(); + if (entry.strict_mode()) top_scope_->EnableStrictMode(); only_simple_this_property_assignments = false; - this_property_assignments = Factory::empty_fixed_array(); + this_property_assignments = isolate()->factory()->empty_fixed_array(); Expect(Token::RBRACE, CHECK_OK); } else { ParseSourceElements(body, Token::RBRACE, CHECK_OK); - materialized_literal_count = temp_scope.materialized_literal_count(); - expected_property_count = temp_scope.expected_property_count(); + materialized_literal_count = lexical_scope.materialized_literal_count(); + expected_property_count = lexical_scope.expected_property_count(); only_simple_this_property_assignments = - temp_scope.only_simple_this_property_assignments(); - this_property_assignments = temp_scope.this_property_assignments(); + lexical_scope.only_simple_this_property_assignments(); + this_property_assignments = lexical_scope.this_property_assignments(); Expect(Token::RBRACE, CHECK_OK); end_pos = scanner().location().end_pos; } // Validate strict mode. - if (temp_scope_->StrictMode()) { + if (top_scope_->is_strict_mode()) { if (IsEvalOrArguments(name)) { int position = function_token_position != RelocInfo::kNoPosition ? function_token_position @@ -3661,7 +3711,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, *ok = false; return NULL; } - if (name_is_reserved) { + if (name_is_strict_reserved) { int position = function_token_position != RelocInfo::kNoPosition ? function_token_position : (start_pos > 0 ? start_pos - 1 : start_pos); @@ -3679,26 +3729,25 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, } CheckOctalLiteral(start_pos, end_pos, CHECK_OK); } + } - FunctionLiteral* function_literal = - new FunctionLiteral(name, - top_scope_, - body, - materialized_literal_count, - expected_property_count, - only_simple_this_property_assignments, - this_property_assignments, - num_parameters, - start_pos, - end_pos, - function_name->length() > 0, - temp_scope.ContainsLoops(), - temp_scope.StrictMode()); - function_literal->set_function_token_position(function_token_position); + FunctionLiteral* function_literal = + new(zone()) FunctionLiteral(name, + scope, + body, + materialized_literal_count, + expected_property_count, + only_simple_this_property_assignments, + this_property_assignments, + num_parameters, + start_pos, + end_pos, + (function_name->length() > 0), + has_duplicate_parameters); + function_literal->set_function_token_position(function_token_position); - if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); - return function_literal; - } + if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); + return function_literal; } @@ -3716,7 +3765,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { top_scope_->ForceEagerCompilation(); } - Runtime::Function* function = Runtime::FunctionForSymbol(name); + const Runtime::Function* function = Runtime::FunctionForSymbol(name); // Check for built-in IS_VAR macro. if (function != NULL && @@ -3744,14 +3793,15 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { } // We have a valid intrinsics call or a call to a builtin. - return new CallRuntime(name, function, args); + return new(zone()) CallRuntime(name, function, args); } bool Parser::peek_any_identifier() { Token::Value next = peek(); return next == Token::IDENTIFIER || - next == Token::FUTURE_RESERVED_WORD; + next == Token::FUTURE_RESERVED_WORD || + next == Token::FUTURE_STRICT_RESERVED_WORD; } @@ -3789,7 +3839,7 @@ void Parser::ExpectSemicolon(bool* ok) { Next(); return; } - if (scanner().has_line_terminator_before_next() || + if (scanner().HasAnyLineTerminatorBeforeNext() || tok == Token::RBRACE || tok == Token::EOS) { return; @@ -3799,12 +3849,12 @@ void Parser::ExpectSemicolon(bool* ok) { Literal* Parser::GetLiteralUndefined() { - return new Literal(Factory::undefined_value()); + return new(zone()) Literal(isolate()->factory()->undefined_value()); } Literal* Parser::GetLiteralTheHole() { - return new Literal(Factory::the_hole_value()); + return new(zone()) Literal(isolate()->factory()->the_hole_value()); } @@ -3813,22 +3863,27 @@ Literal* Parser::GetLiteralNumber(double value) { } +// Parses and identifier that is valid for the current scope, in particular it +// fails on strict mode future reserved keywords in a strict scope. Handle<String> Parser::ParseIdentifier(bool* ok) { - bool is_reserved; - return ParseIdentifierOrReservedWord(&is_reserved, ok); + if (top_scope_->is_strict_mode()) { + Expect(Token::IDENTIFIER, ok); + } else if (!Check(Token::IDENTIFIER)) { + Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); + } + if (!*ok) return Handle<String>(); + return GetSymbol(ok); } -Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved, - bool* ok) { - *is_reserved = false; - if (temp_scope_->StrictMode()) { - Expect(Token::IDENTIFIER, ok); - } else { - if (!Check(Token::IDENTIFIER)) { - Expect(Token::FUTURE_RESERVED_WORD, ok); - *is_reserved = true; - } +// Parses and identifier or a strict mode future reserved word, and indicate +// whether it is strict mode future reserved. +Handle<String> Parser::ParseIdentifierOrStrictReservedWord( + bool* is_strict_reserved, bool* ok) { + *is_strict_reserved = false; + if (!Check(Token::IDENTIFIER)) { + Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); + *is_strict_reserved = true; } if (!*ok) return Handle<String>(); return GetSymbol(ok); @@ -3838,8 +3893,9 @@ Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved, Handle<String> Parser::ParseIdentifierName(bool* ok) { Token::Value next = Next(); if (next != Token::IDENTIFIER && - next != Token::FUTURE_RESERVED_WORD && - !Token::IsKeyword(next)) { + next != Token::FUTURE_RESERVED_WORD && + next != Token::FUTURE_STRICT_RESERVED_WORD && + !Token::IsKeyword(next)) { ReportUnexpectedToken(next); *ok = false; return Handle<String>(); @@ -3853,7 +3909,7 @@ Handle<String> Parser::ParseIdentifierName(bool* ok) { void Parser::CheckStrictModeLValue(Expression* expression, const char* error, bool* ok) { - ASSERT(temp_scope_->StrictMode()); + ASSERT(top_scope_->is_strict_mode()); VariableProxy* lhs = expression != NULL ? expression->AsVariableProxy() : NULL; @@ -3865,12 +3921,14 @@ void Parser::CheckStrictModeLValue(Expression* expression, } -// Checks whether octal literal last seen is between beg_pos and end_pos. -// If so, reports an error. +// Checks whether an octal literal was last seen between beg_pos and end_pos. +// If so, reports an error. Only called for strict mode. void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { - int octal = scanner().octal_position(); - if (beg_pos <= octal && octal <= end_pos) { - ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal", + Scanner::Location octal = scanner().octal_position(); + if (octal.IsValid() && + beg_pos <= octal.beg_pos && + octal.end_pos <= end_pos) { + ReportMessageAt(octal, "strict_octal_literal", Vector<const char*>::empty()); scanner().clear_octal_position(); *ok = false; @@ -3878,12 +3936,12 @@ void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { } -// This function reads an identifier and determines whether or not it +// This function reads an identifier name and determines whether or not it // is 'get' or 'set'. -Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, - bool* is_set, - bool* ok) { - Handle<String> result = ParseIdentifier(ok); +Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get, + bool* is_set, + bool* ok) { + Handle<String> result = ParseIdentifierName(ok); if (!*ok) return Handle<String>(); if (scanner().is_literal_ascii() && scanner().literal_length() == 3) { const char* token = scanner().literal_ascii_string().start(); @@ -3940,7 +3998,7 @@ IterationStatement* Parser::LookupContinueTarget(Handle<String> label, } -void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) { +void Parser::RegisterTargetUse(Label* target, Target* stop) { // Register that a break target found at the given stop in the // target stack has been used from the top of the target stack. Add // the break target to any TargetCollectors passed on the stack. @@ -3952,12 +4010,12 @@ void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) { Literal* Parser::NewNumberLiteral(double number) { - return new Literal(Factory::NewNumber(number, TENURED)); + return new(zone()) Literal(isolate()->factory()->NewNumber(number, TENURED)); } Expression* Parser::NewThrowReferenceError(Handle<String> type) { - return NewThrowError(Factory::MakeReferenceError_symbol(), + return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(), type, HandleVector<Object>(NULL, 0)); } @@ -3966,7 +4024,8 @@ Expression* Parser::NewThrowSyntaxError(Handle<String> type, Handle<Object> first) { int argc = first.is_null() ? 0 : 1; Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc); - return NewThrowError(Factory::MakeSyntaxError_symbol(), type, arguments); + return NewThrowError( + isolate()->factory()->MakeSyntaxError_symbol(), type, arguments); } @@ -3977,7 +4036,8 @@ Expression* Parser::NewThrowTypeError(Handle<String> type, Handle<Object> elements[] = { first, second }; Vector< Handle<Object> > arguments = HandleVector<Object>(elements, ARRAY_SIZE(elements)); - return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments); + return NewThrowError( + isolate()->factory()->MakeTypeError_symbol(), type, arguments); } @@ -3985,215 +4045,44 @@ Expression* Parser::NewThrowError(Handle<String> constructor, Handle<String> type, Vector< Handle<Object> > arguments) { int argc = arguments.length(); - Handle<FixedArray> elements = Factory::NewFixedArray(argc, TENURED); + Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc, + TENURED); for (int i = 0; i < argc; i++) { Handle<Object> element = arguments[i]; if (!element.is_null()) { elements->set(i, *element); } } - Handle<JSArray> array = Factory::NewJSArrayWithElements(elements, TENURED); + Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements, + TENURED); - ZoneList<Expression*>* args = new ZoneList<Expression*>(2); - args->Add(new Literal(type)); - args->Add(new Literal(array)); - return new Throw(new CallRuntime(constructor, NULL, args), + ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2); + args->Add(new(zone()) Literal(type)); + args->Add(new(zone()) Literal(array)); + return new(zone()) Throw(new(zone()) CallRuntime(constructor, NULL, args), scanner().location().beg_pos); } // ---------------------------------------------------------------------------- -// JSON - -Handle<Object> JsonParser::ParseJson(Handle<String> script, - UC16CharacterStream* source) { - scanner_.Initialize(source); - stack_overflow_ = false; - Handle<Object> result = ParseJsonValue(); - if (result.is_null() || scanner_.Next() != Token::EOS) { - if (stack_overflow_) { - // Scanner failed. - Top::StackOverflow(); - } else { - // Parse failed. Scanner's current token is the unexpected token. - Token::Value token = scanner_.current_token(); - - const char* message; - const char* name_opt = NULL; - - switch (token) { - case Token::EOS: - message = "unexpected_eos"; - break; - case Token::NUMBER: - message = "unexpected_token_number"; - break; - case Token::STRING: - message = "unexpected_token_string"; - break; - case Token::IDENTIFIER: - case Token::FUTURE_RESERVED_WORD: - message = "unexpected_token_identifier"; - break; - default: - message = "unexpected_token"; - name_opt = Token::String(token); - ASSERT(name_opt != NULL); - break; - } - - Scanner::Location source_location = scanner_.location(); - MessageLocation location(Factory::NewScript(script), - source_location.beg_pos, - source_location.end_pos); - int argc = (name_opt == NULL) ? 0 : 1; - Handle<JSArray> array = Factory::NewJSArray(argc); - if (name_opt != NULL) { - SetElement(array, - 0, - Factory::NewStringFromUtf8(CStrVector(name_opt))); - } - Handle<Object> result = Factory::NewSyntaxError(message, array); - Top::Throw(*result, &location); - return Handle<Object>::null(); - } - } - return result; -} - - -Handle<String> JsonParser::GetString() { - int literal_length = scanner_.literal_length(); - if (literal_length == 0) { - return Factory::empty_string(); - } - if (scanner_.is_literal_ascii()) { - return Factory::NewStringFromAscii(scanner_.literal_ascii_string()); - } else { - return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string()); - } -} - - -// Parse any JSON value. -Handle<Object> JsonParser::ParseJsonValue() { - Token::Value token = scanner_.Next(); - switch (token) { - case Token::STRING: - return GetString(); - case Token::NUMBER: - return Factory::NewNumber(scanner_.number()); - case Token::FALSE_LITERAL: - return Factory::false_value(); - case Token::TRUE_LITERAL: - return Factory::true_value(); - case Token::NULL_LITERAL: - return Factory::null_value(); - case Token::LBRACE: - return ParseJsonObject(); - case Token::LBRACK: - return ParseJsonArray(); - default: - return ReportUnexpectedToken(); - } -} - - -// Parse a JSON object. Scanner must be right after '{' token. -Handle<Object> JsonParser::ParseJsonObject() { - Handle<JSFunction> object_constructor( - Top::global_context()->object_function()); - Handle<JSObject> json_object = Factory::NewJSObject(object_constructor); - if (scanner_.peek() == Token::RBRACE) { - scanner_.Next(); - } else { - if (StackLimitCheck().HasOverflowed()) { - stack_overflow_ = true; - return Handle<Object>::null(); - } - do { - if (scanner_.Next() != Token::STRING) { - return ReportUnexpectedToken(); - } - Handle<String> key = GetString(); - if (scanner_.Next() != Token::COLON) { - return ReportUnexpectedToken(); - } - Handle<Object> value = ParseJsonValue(); - if (value.is_null()) return Handle<Object>::null(); - uint32_t index; - if (key->AsArrayIndex(&index)) { - SetOwnElement(json_object, index, value); - } else if (key->Equals(Heap::Proto_symbol())) { - // We can't remove the __proto__ accessor since it's hardcoded - // in several places. Instead go along and add the value as - // the prototype of the created object if possible. - SetPrototype(json_object, value); - } else { - SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE); - } - } while (scanner_.Next() == Token::COMMA); - if (scanner_.current_token() != Token::RBRACE) { - return ReportUnexpectedToken(); - } - } - return json_object; -} - - -// Parse a JSON array. Scanner must be right after '[' token. -Handle<Object> JsonParser::ParseJsonArray() { - ZoneScope zone_scope(DELETE_ON_EXIT); - ZoneList<Handle<Object> > elements(4); - - Token::Value token = scanner_.peek(); - if (token == Token::RBRACK) { - scanner_.Next(); - } else { - if (StackLimitCheck().HasOverflowed()) { - stack_overflow_ = true; - return Handle<Object>::null(); - } - do { - Handle<Object> element = ParseJsonValue(); - if (element.is_null()) return Handle<Object>::null(); - elements.Add(element); - token = scanner_.Next(); - } while (token == Token::COMMA); - if (token != Token::RBRACK) { - return ReportUnexpectedToken(); - } - } - - // Allocate a fixed array with all the elements. - Handle<FixedArray> fast_elements = - Factory::NewFixedArray(elements.length()); - - for (int i = 0, n = elements.length(); i < n; i++) { - fast_elements->set(i, *elements[i]); - } - - return Factory::NewJSArrayWithElements(fast_elements); -} - -// ---------------------------------------------------------------------------- // Regular expressions RegExpParser::RegExpParser(FlatStringReader* in, Handle<String>* error, bool multiline) - : error_(error), - captures_(NULL), - in_(in), - current_(kEndMarker), - next_pos_(0), - capture_count_(0), - has_more_(true), - multiline_(multiline), - simple_(false), - contains_anchor_(false), - is_scanned_for_captures_(false), - failed_(false) { + : isolate_(Isolate::Current()), + error_(error), + captures_(NULL), + in_(in), + current_(kEndMarker), + next_pos_(0), + capture_count_(0), + has_more_(true), + multiline_(multiline), + simple_(false), + contains_anchor_(false), + is_scanned_for_captures_(false), + failed_(false) { Advance(); } @@ -4209,10 +4098,10 @@ uc32 RegExpParser::Next() { void RegExpParser::Advance() { if (next_pos_ < in()->length()) { - StackLimitCheck check; + StackLimitCheck check(isolate()); if (check.HasOverflowed()) { - ReportError(CStrVector(Top::kStackOverflowMessage)); - } else if (Zone::excess_allocation()) { + ReportError(CStrVector(Isolate::kStackOverflowMessage)); + } else if (isolate()->zone()->excess_allocation()) { ReportError(CStrVector("Regular expression too large")); } else { current_ = in()->Get(next_pos_); @@ -4243,7 +4132,7 @@ bool RegExpParser::simple() { RegExpTree* RegExpParser::ReportError(Vector<const char> message) { failed_ = true; - *error_ = Factory::NewStringFromAscii(message, NOT_TENURED); + *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED); // Zip to the end to make sure the no more input is read. current_ = kEndMarker; next_pos_ = in()->length(); @@ -4313,13 +4202,13 @@ RegExpTree* RegExpParser::ParseDisjunction() { // Build result of subexpression. if (type == CAPTURE) { - RegExpCapture* capture = new RegExpCapture(body, capture_index); + RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index); captures_->at(capture_index - 1) = capture; body = capture; } else if (type != GROUPING) { ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD); bool is_positive = (type == POSITIVE_LOOKAHEAD); - body = new RegExpLookahead(body, + body = new(zone()) RegExpLookahead(body, is_positive, end_capture_index - capture_index, capture_index); @@ -4342,10 +4231,10 @@ RegExpTree* RegExpParser::ParseDisjunction() { Advance(); if (multiline_) { builder->AddAssertion( - new RegExpAssertion(RegExpAssertion::START_OF_LINE)); + new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE)); } else { builder->AddAssertion( - new RegExpAssertion(RegExpAssertion::START_OF_INPUT)); + new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); set_contains_anchor(); } continue; @@ -4355,15 +4244,16 @@ RegExpTree* RegExpParser::ParseDisjunction() { RegExpAssertion::Type type = multiline_ ? RegExpAssertion::END_OF_LINE : RegExpAssertion::END_OF_INPUT; - builder->AddAssertion(new RegExpAssertion(type)); + builder->AddAssertion(new(zone()) RegExpAssertion(type)); continue; } case '.': { Advance(); // everything except \x0a, \x0d, \u2028 and \u2029 - ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2); + ZoneList<CharacterRange>* ranges = + new(zone()) ZoneList<CharacterRange>(2); CharacterRange::AddClassEscape('.', ranges); - RegExpTree* atom = new RegExpCharacterClass(ranges, false); + RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false); builder->AddAtom(atom); break; } @@ -4388,7 +4278,7 @@ RegExpTree* RegExpParser::ParseDisjunction() { Advance(2); } else { if (captures_ == NULL) { - captures_ = new ZoneList<RegExpCapture*>(2); + captures_ = new(zone()) ZoneList<RegExpCapture*>(2); } if (captures_started() >= kMaxCaptures) { ReportError(CStrVector("Too many captures") CHECK_FAILED); @@ -4396,7 +4286,7 @@ RegExpTree* RegExpParser::ParseDisjunction() { captures_->Add(NULL); } // Store current state and begin new disjunction parsing. - stored_state = new RegExpParserState(stored_state, + stored_state = new(zone()) RegExpParserState(stored_state, type, captures_started()); builder = stored_state->builder(); @@ -4416,12 +4306,12 @@ RegExpTree* RegExpParser::ParseDisjunction() { case 'b': Advance(2); builder->AddAssertion( - new RegExpAssertion(RegExpAssertion::BOUNDARY)); + new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY)); continue; case 'B': Advance(2); builder->AddAssertion( - new RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); + new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); continue; // AtomEscape :: // CharacterClassEscape @@ -4431,9 +4321,10 @@ RegExpTree* RegExpParser::ParseDisjunction() { case 'd': case 'D': case 's': case 'S': case 'w': case 'W': { uc32 c = Next(); Advance(2); - ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2); + ZoneList<CharacterRange>* ranges = + new(zone()) ZoneList<CharacterRange>(2); CharacterRange::AddClassEscape(c, ranges); - RegExpTree* atom = new RegExpCharacterClass(ranges, false); + RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false); builder->AddAtom(atom); break; } @@ -4449,7 +4340,7 @@ RegExpTree* RegExpParser::ParseDisjunction() { builder->AddEmpty(); break; } - RegExpTree* atom = new RegExpBackReference(capture); + RegExpTree* atom = new(zone()) RegExpBackReference(capture); builder->AddAtom(atom); break; } @@ -4597,30 +4488,6 @@ RegExpTree* RegExpParser::ParseDisjunction() { } } -class SourceCharacter { - public: - static bool Is(uc32 c) { - switch (c) { - // case ']': case '}': - // In spidermonkey and jsc these are treated as source characters - // so we do too. - case '^': case '$': case '\\': case '.': case '*': case '+': - case '?': case '(': case ')': case '[': case '{': case '|': - case RegExpParser::kEndMarker: - return false; - default: - return true; - } - } -}; - - -static unibrow::Predicate<SourceCharacter> source_character; - - -static inline bool IsSourceCharacter(uc32 c) { - return source_character.get(c); -} #ifdef DEBUG // Currently only used in an ASSERT. @@ -4951,7 +4818,7 @@ RegExpTree* RegExpParser::ParseCharacterClass() { is_negated = true; Advance(); } - ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2); + ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2); while (has_more() && current() != ']') { uc16 char_class = kNoCharClass; CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); @@ -4991,7 +4858,7 @@ RegExpTree* RegExpParser::ParseCharacterClass() { ranges->Add(CharacterRange::Everything()); is_negated = !is_negated; } - return new RegExpCharacterClass(ranges, is_negated); + return new(zone()) RegExpCharacterClass(ranges, is_negated); } @@ -5073,14 +4940,15 @@ int ScriptDataImpl::ReadNumber(byte** source) { static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, bool allow_lazy, ParserRecorder* recorder) { - V8JavaScriptScanner scanner; + Isolate* isolate = Isolate::Current(); + JavaScriptScanner scanner(isolate->unicode_cache()); scanner.Initialize(source); - intptr_t stack_limit = StackGuard::real_climit(); + intptr_t stack_limit = isolate->stack_guard()->real_climit(); if (!preparser::PreParser::PreParseProgram(&scanner, recorder, allow_lazy, stack_limit)) { - Top::StackOverflow(); + isolate->StackOverflow(); return NULL; } @@ -5145,8 +5013,9 @@ bool ParserApi::Parse(CompilationInfo* info) { Parser parser(script, true, NULL, NULL); result = parser.ParseLazy(info); } else { + // Whether we allow %identifier(..) syntax. bool allow_natives_syntax = - FLAG_allow_natives_syntax || Bootstrapper::IsActive(); + info->allows_natives_syntax() || FLAG_allow_natives_syntax; ScriptDataImpl* pre_data = info->pre_parse_data(); Parser parser(script, allow_natives_syntax, info->extension(), pre_data); if (pre_data != NULL && pre_data->has_error()) { @@ -5159,7 +5028,7 @@ bool ParserApi::Parse(CompilationInfo* info) { DeleteArray(args[i]); } DeleteArray(args.start()); - ASSERT(Top::has_pending_exception()); + ASSERT(info->isolate()->has_pending_exception()); } else { Handle<String> source = Handle<String>(String::cast(script->source())); result = parser.ParseProgram(source, |