Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index f07f37ebb2b271cc6466ff2dde8af462adb0a9a7..5788c50d201ddda36a53b5cdc105390b0ed65ad2 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -300,19 +300,16 @@ const char* ScriptData::BuildMessage() const { |
| } |
| -Vector<const char*> ScriptData::BuildArgs() const { |
| +const char* ScriptData::BuildArg() const { |
| int arg_count = Read(PreparseDataConstants::kMessageArgCountPos); |
| - const char** array = NewArray<const char*>(arg_count); |
| + if (arg_count == 0) |
| + return NULL; |
| // Position after text found by skipping past length field and |
| // length field content words. |
| int pos = PreparseDataConstants::kMessageTextPos + 1 |
| + Read(PreparseDataConstants::kMessageTextPos); |
| - for (int i = 0; i < arg_count; i++) { |
| - int count = 0; |
| - array[i] = ReadString(ReadAddress(pos), &count); |
| - pos += count + 1; |
| - } |
| - return Vector<const char*>(array, arg_count); |
| + int count = 0; |
| + return ReadString(ReadAddress(pos), &count); |
| } |
| @@ -327,7 +324,8 @@ unsigned* ScriptData::ReadAddress(int position) const { |
| Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { |
| - Scope* result = new(zone()) Scope(parent, scope_type, zone()); |
| + ASSERT(symbol_table_); |
| + Scope* result = new(zone()) Scope(parent, scope_type, symbol_table_, zone()); |
| result->Initialize(); |
| return result; |
| } |
| @@ -400,10 +398,10 @@ class TargetScope BASE_EMBEDDED { |
| // ---------------------------------------------------------------------------- |
| // Implementation of Parser |
| -bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const { |
| - Factory* factory = parser_->isolate()->factory(); |
| - return identifier.is_identical_to(factory->eval_string()) |
| - || identifier.is_identical_to(factory->arguments_string()); |
| +bool ParserTraits::IsEvalOrArguments( |
| + ParserSymbolTable::Symbol* identifier) const { |
| + return identifier == parser_->symbol_table_->eval_string() || |
| + identifier == parser_->symbol_table_->arguments_string(); |
| } |
| @@ -425,10 +423,9 @@ bool ParserTraits::IsIdentifier(Expression* expression) { |
| void ParserTraits::PushPropertyName(FuncNameInferrer* fni, |
| Expression* expression) { |
| if (expression->IsPropertyName()) { |
| - fni->PushLiteralName(expression->AsLiteral()->AsPropertyName()); |
| + fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName()); |
| } else { |
| - fni->PushLiteralName( |
| - parser_->isolate()->factory()->anonymous_function_string()); |
| + fni->PushLiteralName(parser_->symbol_table_->anonymous_function_string()); |
| } |
| } |
| @@ -447,7 +444,7 @@ void ParserTraits::CheckPossibleEvalCall(Expression* expression, |
| Scope* scope) { |
| VariableProxy* callee = expression->AsVariableProxy(); |
| if (callee != NULL && |
| - callee->IsVariable(parser_->isolate()->factory()->eval_string())) { |
| + callee->raw_name() == parser_->symbol_table_->eval_string()) { |
| scope->DeclarationScope()->RecordEvalCall(); |
| } |
| } |
| @@ -465,10 +462,13 @@ Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) { |
| bool ParserTraits::ShortcutNumericLiteralBinaryExpression( |
| Expression** x, Expression* y, Token::Value op, int pos, |
| AstNodeFactory<AstConstructionVisitor>* factory) { |
| - if ((*x)->AsLiteral() && (*x)->AsLiteral()->value()->IsNumber() && |
| - y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) { |
| - double x_val = (*x)->AsLiteral()->value()->Number(); |
| - double y_val = y->AsLiteral()->value()->Number(); |
| + // FIXME: this needs to change when it cannot use handles. |
| + if ((*x)->AsLiteral() && !(*x)->AsLiteral()->valueIfNotString().is_null() && |
| + (*x)->AsLiteral()->valueIfNotString()->IsNumber() && y->AsLiteral() && |
| + !y->AsLiteral()->valueIfNotString().is_null() && |
| + y->AsLiteral()->valueIfNotString()->IsNumber()) { |
| + double x_val = (*x)->AsLiteral()->valueIfNotString()->Number(); |
| + double y_val = y->AsLiteral()->valueIfNotString()->Number(); |
| switch (op) { |
| case Token::ADD: |
| *x = factory->NewNumberLiteral(x_val + y_val, pos); |
| @@ -526,8 +526,12 @@ Expression* ParserTraits::BuildUnaryExpression( |
| Expression* expression, Token::Value op, int pos, |
| AstNodeFactory<AstConstructionVisitor>* factory) { |
| ASSERT(expression != NULL); |
| - if (expression->AsLiteral() != NULL) { |
| - Handle<Object> literal = expression->AsLiteral()->value(); |
| + // FIXME: This needs to change when numbers and booleans are no longer |
| + // handles. |
| + // FIXME: The !"foo" shortcut doesn't work atm. |
| + if (expression->AsLiteral() != NULL && |
| + !expression->AsLiteral()->valueIfNotString().is_null()) { |
| + Handle<Object> literal = expression->AsLiteral()->valueIfNotString(); |
| if (op == Token::NOT) { |
| // Convert the literal to a boolean condition and negate it. |
| bool condition = literal->BooleanValue(); |
| @@ -569,52 +573,40 @@ Expression* ParserTraits::BuildUnaryExpression( |
| Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) { |
| - return NewThrowError( |
| - parser_->isolate()->factory()->MakeReferenceError_string(), |
| - message, HandleVector<Object>(NULL, 0), pos); |
| + return NewThrowError(parser_->symbol_table_->make_reference_error_string(), |
| + message, NULL, pos); |
| } |
| Expression* ParserTraits::NewThrowSyntaxError( |
| - const char* message, Handle<Object> arg, int pos) { |
| - int argc = arg.is_null() ? 0 : 1; |
| - Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc); |
| - return NewThrowError( |
| - parser_->isolate()->factory()->MakeSyntaxError_string(), |
| - message, arguments, pos); |
| + const char* message, ParserSymbolTable::Symbol* arg, int pos) { |
| + return NewThrowError(parser_->symbol_table_->make_syntax_error_string(), |
| + message, arg, pos); |
| } |
| Expression* ParserTraits::NewThrowTypeError( |
| - const char* message, Handle<Object> arg, int pos) { |
| - int argc = arg.is_null() ? 0 : 1; |
| - Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc); |
| - return NewThrowError( |
| - parser_->isolate()->factory()->MakeTypeError_string(), |
| - message, arguments, pos); |
| + const char* message, ParserSymbolTable::Symbol* arg, int pos) { |
| + return NewThrowError(parser_->symbol_table_->make_type_error_string(), |
| + message, arg, pos); |
| } |
| Expression* ParserTraits::NewThrowError( |
| - Handle<String> constructor, const char* message, |
| - Vector<Handle<Object> > arguments, int pos) { |
| + ParserSymbolTable::Symbol* constructor, const char* message, |
| + ParserSymbolTable::Symbol* arg, int pos) { |
| Zone* zone = parser_->zone(); |
| - Factory* factory = parser_->isolate()->factory(); |
| - int argc = arguments.length(); |
| - Handle<FixedArray> elements = 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, FAST_ELEMENTS, TENURED); |
| - |
| - ZoneList<Expression*>* args = new(zone) ZoneList<Expression*>(2, zone); |
| - Handle<String> type = factory->InternalizeUtf8String(message); |
| + ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(arg != NULL ? 2 : 1, zone); |
| + ParserSymbolTable::Symbol* type = |
| + parser_->symbol_table_->GetOneByteSymbol(Vector<const uint8_t>( |
| + reinterpret_cast<const uint8_t*>(message), StrLength(message))); |
| args->Add(parser_->factory()->NewLiteral(type, pos), zone); |
| - args->Add(parser_->factory()->NewLiteral(array, pos), zone); |
| + if (arg != NULL) { |
| + ZoneList<ParserSymbolTable::Symbol*>* array = |
| + new (zone) ZoneList<ParserSymbolTable::Symbol*>(1, zone); |
| + array->Add(arg, zone); |
| + args->Add(parser_->factory()->NewLiteral(array, pos), zone); |
| + } |
| CallRuntime* call_constructor = |
| parser_->factory()->NewCallRuntime(constructor, NULL, args, pos); |
| return parser_->factory()->NewThrow(call_constructor, pos); |
| @@ -623,7 +615,7 @@ Expression* ParserTraits::NewThrowError( |
| void ParserTraits::ReportMessageAt(Scanner::Location source_location, |
| const char* message, |
| - Vector<const char*> args, |
| + const char* char_arg, |
| bool is_reference_error) { |
| if (parser_->stack_overflow()) { |
| // Suppress the error message (syntax error or such) in the presence of a |
| @@ -631,35 +623,18 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location, |
| // and we want to report the stack overflow later. |
| return; |
| } |
| - MessageLocation location(parser_->script_, |
| - source_location.beg_pos, |
| - source_location.end_pos); |
| - Factory* factory = parser_->isolate()->factory(); |
| - Handle<FixedArray> elements = factory->NewFixedArray(args.length()); |
| - for (int i = 0; i < args.length(); i++) { |
| - Handle<String> arg_string = |
| - factory->NewStringFromUtf8(CStrVector(args[i])).ToHandleChecked(); |
| - elements->set(i, *arg_string); |
| - } |
| - Handle<JSArray> array = factory->NewJSArrayWithElements(elements); |
| - Handle<Object> result = is_reference_error |
| - ? factory->NewReferenceError(message, array) |
| - : factory->NewSyntaxError(message, array); |
| - parser_->isolate()->Throw(*result, &location); |
| -} |
| - |
| - |
| -void ParserTraits::ReportMessage(const char* message, |
| - Vector<Handle<String> > args, |
| - bool is_reference_error) { |
| - Scanner::Location source_location = parser_->scanner()->location(); |
| - ReportMessageAt(source_location, message, args, is_reference_error); |
| + parser_->has_pending_error_ = true; |
| + parser_->pending_location_ = source_location; |
| + parser_->pending_message_ = message; |
| + parser_->pending_char_arg_ = char_arg; |
| + parser_->pending_arg_ = NULL; |
| + parser_->pending_is_reference_error_ = is_reference_error; |
| } |
| void ParserTraits::ReportMessageAt(Scanner::Location source_location, |
| const char* message, |
| - Vector<Handle<String> > args, |
| + ParserSymbolTable::Symbol* arg, |
| bool is_reference_error) { |
| if (parser_->stack_overflow()) { |
| // Suppress the error message (syntax error or such) in the presence of a |
| @@ -667,33 +642,38 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location, |
| // and we want to report the stack overflow later. |
| return; |
| } |
| - MessageLocation location(parser_->script_, |
| - source_location.beg_pos, |
| - source_location.end_pos); |
| - Factory* factory = parser_->isolate()->factory(); |
| - Handle<FixedArray> elements = factory->NewFixedArray(args.length()); |
| - for (int i = 0; i < args.length(); i++) { |
| - elements->set(i, *args[i]); |
| - } |
| - Handle<JSArray> array = factory->NewJSArrayWithElements(elements); |
| - Handle<Object> result = is_reference_error |
| - ? factory->NewReferenceError(message, array) |
| - : factory->NewSyntaxError(message, array); |
| - parser_->isolate()->Throw(*result, &location); |
| + parser_->has_pending_error_ = true; |
| + parser_->pending_location_ = source_location; |
| + parser_->pending_message_ = message; |
| + parser_->pending_char_arg_ = NULL; |
| + parser_->pending_arg_ = arg; |
| + parser_->pending_is_reference_error_ = is_reference_error; |
| } |
| -Handle<String> ParserTraits::GetSymbol(Scanner* scanner) { |
| - Handle<String> result = |
| - parser_->scanner()->AllocateInternalizedString(parser_->isolate()); |
| - ASSERT(!result.is_null()); |
| - return result; |
| +void ParserTraits::ReportMessage(const char* message, |
| + const char* char_arg, |
| + bool is_reference_error) { |
| + Scanner::Location source_location = parser_->scanner()->location(); |
| + ReportMessageAt(source_location, message, char_arg, is_reference_error); |
| +} |
| + |
| + |
| +void ParserTraits::ReportMessage(const char* message, |
| + ParserSymbolTable::Symbol* arg, |
| + bool is_reference_error) { |
| + Scanner::Location source_location = parser_->scanner()->location(); |
| + ReportMessageAt(source_location, message, arg, is_reference_error); |
| } |
| -Handle<String> ParserTraits::NextLiteralString(Scanner* scanner, |
| - PretenureFlag tenured) { |
| - return scanner->AllocateNextLiteralString(parser_->isolate(), tenured); |
| +ParserSymbolTable::Symbol* ParserTraits::GetSymbol(Scanner* scanner) { |
| + return parser_->scanner()->CurrentString(parser_->symbol_table_); |
| +} |
| + |
| + |
| +ParserSymbolTable::Symbol* ParserTraits::GetNextSymbol(Scanner* scanner) { |
| + return parser_->scanner()->NextString(parser_->symbol_table_); |
| } |
| @@ -728,13 +708,17 @@ Literal* ParserTraits::ExpressionFromLiteral( |
| Expression* ParserTraits::ExpressionFromIdentifier( |
| - Handle<String> name, int pos, Scope* scope, |
| + ParserSymbolTable::Symbol* name, int pos, Scope* scope, |
| AstNodeFactory<AstConstructionVisitor>* factory) { |
| - if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name); |
| + if (parser_->fni_ != NULL) { |
| + parser_->fni_->PushVariableName(name); |
| + } |
| // The name may refer to a module instance object, so its type is unknown. |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Variable %s ", name->ToAsciiArray()); |
| + if (FLAG_print_interface_details) { |
| + PrintF("# Variable %.*s ", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| + } |
| #endif |
| Interface* interface = Interface::NewUnknown(parser_->zone()); |
| return scope->NewUnresolved(factory, name, interface, pos); |
| @@ -744,7 +728,7 @@ Expression* ParserTraits::ExpressionFromIdentifier( |
| Expression* ParserTraits::ExpressionFromString( |
| int pos, Scanner* scanner, |
| AstNodeFactory<AstConstructionVisitor>* factory) { |
| - Handle<String> symbol = GetSymbol(scanner); |
| + ParserSymbolTable::Symbol* symbol = GetSymbol(scanner); |
| if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol); |
| return factory->NewLiteral(symbol, pos); |
| } |
| @@ -763,7 +747,7 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { |
| FunctionLiteral* ParserTraits::ParseFunctionLiteral( |
| - Handle<String> name, |
| + ParserSymbolTable::Symbol* name, |
| Scanner::Location function_name_location, |
| bool name_is_strict_reserved, |
| bool is_generator, |
| @@ -791,7 +775,12 @@ Parser::Parser(CompilationInfo* info) |
| target_stack_(NULL), |
| cached_data_(NULL), |
| cached_data_mode_(NO_CACHED_DATA), |
| - info_(info) { |
| + symbol_table_(NULL), |
| + info_(info), |
| + has_pending_error_(false), |
| + pending_message_(NULL), |
| + pending_arg_(NULL), |
| + pending_char_arg_(NULL) { |
| ASSERT(!script_.is_null()); |
| isolate_->set_ast_node_id(0); |
| set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); |
| @@ -814,7 +803,7 @@ FunctionLiteral* Parser::ParseProgram() { |
| if (FLAG_trace_parse) { |
| timer.Start(); |
| } |
| - fni_ = new(zone()) FuncNameInferrer(isolate(), zone()); |
| + fni_ = new(zone()) FuncNameInferrer(symbol_table_, zone()); |
| // Initialize parser state. |
| CompleteParserRecorder recorder; |
| @@ -869,13 +858,14 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
| ASSERT(scope_ == NULL); |
| ASSERT(target_stack_ == NULL); |
| - Handle<String> no_name = isolate()->factory()->empty_string(); |
| + ParserSymbolTable::Symbol* no_name = symbol_table_->empty_string(); |
| FunctionLiteral* result = NULL; |
| { Scope* scope = NewScope(scope_, GLOBAL_SCOPE); |
| info->SetGlobalScope(scope); |
| if (!info->context().is_null()) { |
| scope = Scope::DeserializeScopeChain(*info->context(), scope, zone()); |
| + symbol_table_->AlwaysInternalize(isolate()); |
| } |
| original_scope_ = scope; |
| if (info->is_eval()) { |
| @@ -918,11 +908,13 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
| !body->at(0)->IsExpressionStatement() || |
| !body->at(0)->AsExpressionStatement()-> |
| expression()->IsFunctionLiteral()) { |
| - ReportMessage("single_function_literal", Vector<const char*>::empty()); |
| + ParserTraits::ReportMessage("single_function_literal"); |
| ok = false; |
| } |
| } |
| + symbol_table_->Internalize(isolate()); |
| + |
| if (ok) { |
| result = factory()->NewFunctionLiteral( |
| no_name, |
| @@ -941,8 +933,11 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
| result->set_ast_properties(factory()->visitor()->ast_properties()); |
| result->set_dont_optimize_reason( |
| factory()->visitor()->dont_optimize_reason()); |
| + |
| } else if (stack_overflow()) { |
| isolate()->StackOverflow(); |
| + } else { |
| + CheckPendingError(); |
| } |
| } |
| @@ -995,8 +990,9 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { |
| ASSERT(target_stack_ == NULL); |
| Handle<String> name(String::cast(shared_info->name())); |
| - fni_ = new(zone()) FuncNameInferrer(isolate(), zone()); |
| - fni_->PushEnclosingName(name); |
| + fni_ = new(zone()) FuncNameInferrer(symbol_table_, zone()); |
| + ParserSymbolTable::Symbol* raw_name = symbol_table_->GetSymbol(name); |
| + fni_->PushEnclosingName(raw_name); |
| ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
| @@ -1022,7 +1018,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { |
| : FunctionLiteral::NAMED_EXPRESSION) |
| : FunctionLiteral::DECLARATION; |
| bool ok = true; |
| - result = ParseFunctionLiteral(name, |
| + result = ParseFunctionLiteral(raw_name, |
| Scanner::Location::invalid(), |
| false, // Strict mode name already checked. |
| shared_info->is_generator(), |
| @@ -1031,13 +1027,20 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { |
| &ok); |
| // Make sure the results agree. |
| ASSERT(ok == (result != NULL)); |
| + |
| + // Start using the heap (before scope goes out of scope). |
|
rossberg
2014/05/08 12:52:08
"scope is exited"?
marja
2014/06/03 08:48:20
Actually, this is not needed any more, so moved th
|
| + symbol_table_->Internalize(isolate()); |
| } |
| // Make sure the target stack is empty. |
| ASSERT(target_stack_ == NULL); |
| if (result == NULL) { |
| - if (stack_overflow()) isolate()->StackOverflow(); |
| + if (stack_overflow()) { |
| + isolate()->StackOverflow(); |
| + } else { |
| + CheckPendingError(); |
| + } |
| } else { |
| Handle<String> inferred_name(shared_info->inferred_name()); |
| result->set_inferred_name(inferred_name); |
| @@ -1087,15 +1090,11 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
| // Still processing directive prologue? |
| if ((e_stat = stat->AsExpressionStatement()) != NULL && |
| (literal = e_stat->expression()->AsLiteral()) != NULL && |
| - literal->value()->IsString()) { |
| - Handle<String> directive = Handle<String>::cast(literal->value()); |
| - |
| + literal->string() != NULL) { |
|
rossberg
2014/05/08 12:52:08
Would be nicer to have an IsString predicate on Li
marja
2014/06/03 08:48:20
The StringLiteral / StringArrayLiteral / Literal s
|
| // Check "use strict" directive (ES5 14.1). |
| if (strict_mode() == SLOPPY && |
| - String::Equals(isolate()->factory()->use_strict_string(), |
| - directive) && |
| - token_loc.end_pos - token_loc.beg_pos == |
| - isolate()->heap()->use_strict_string()->length() + 2) { |
| + literal->string() == symbol_table_->use_strict_string() && |
| + token_loc.end_pos - token_loc.beg_pos == 12) { |
| // TODO(mstarzinger): Global strict eval calls, need their own scope |
| // as specified in ES5 10.4.2(3). The correct fix would be to always |
| // add this scope in DoParseProgram(), but that requires adaptations |
| @@ -1126,8 +1125,8 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
| } |
| -Statement* Parser::ParseModuleElement(ZoneStringList* labels, |
| - bool* ok) { |
| +Statement* Parser::ParseModuleElement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // (Ecma 262 5th Edition, clause 14): |
| // SourceElement: |
| // Statement |
| @@ -1160,10 +1159,9 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels, |
| !scanner()->HasAnyLineTerminatorBeforeNext() && |
| stmt != NULL) { |
| ExpressionStatement* estmt = stmt->AsExpressionStatement(); |
| - if (estmt != NULL && |
| - estmt->expression()->AsVariableProxy() != NULL && |
| - String::Equals(isolate()->factory()->module_string(), |
| - estmt->expression()->AsVariableProxy()->name()) && |
| + if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL && |
| + estmt->expression()->AsVariableProxy()->raw_name() == |
| + symbol_table_->module_string() && |
| !scanner()->literal_contains_escapes()) { |
| return ParseModuleDeclaration(NULL, ok); |
| } |
| @@ -1174,16 +1172,20 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels, |
| } |
| -Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) { |
| +Statement* Parser::ParseModuleDeclaration( |
| + ZoneList<ParserSymbolTable::Symbol*>* names, bool* ok) { |
| // ModuleDeclaration: |
| // 'module' Identifier Module |
| int pos = peek_position(); |
| - Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| + ParserSymbolTable::Symbol* name = |
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Module %s...\n", name->ToAsciiArray()); |
| + if (FLAG_print_interface_details) { |
| + PrintF("# Module %.*s ", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| + } |
| #endif |
| Module* module = ParseModule(CHECK_OK); |
| @@ -1193,11 +1195,13 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) { |
| Declare(declaration, true, CHECK_OK); |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Module %s.\n", name->ToAsciiArray()); |
| - |
| + if (FLAG_print_interface_details) { |
| + PrintF("# Module %.*s ", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| + } |
| if (FLAG_print_interfaces) { |
| - PrintF("module %s : ", name->ToAsciiArray()); |
| + PrintF("module %.*s: ", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| module->interface()->Print(); |
| } |
| #endif |
| @@ -1276,9 +1280,7 @@ Module* Parser::ParseModuleLiteral(bool* ok) { |
| for (Interface::Iterator it = interface->iterator(); |
| !it.done(); it.Advance()) { |
| if (scope->LocalLookup(it.name()) == NULL) { |
| - Handle<String> name(it.name()); |
| - ParserTraits::ReportMessage("module_export_undefined", |
| - Vector<Handle<String> >(&name, 1)); |
| + ParserTraits::ReportMessage("module_export_undefined", it.name()); |
| *ok = false; |
| return NULL; |
| } |
| @@ -1300,25 +1302,28 @@ Module* Parser::ParseModulePath(bool* ok) { |
| int pos = peek_position(); |
| Module* result = ParseModuleVariable(CHECK_OK); |
| while (Check(Token::PERIOD)) { |
| - Handle<String> name = ParseIdentifierName(CHECK_OK); |
| + ParserSymbolTable::Symbol* name = ParseIdentifierName(CHECK_OK); |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Path .%s ", name->ToAsciiArray()); |
| + if (FLAG_print_interface_details) { |
| + PrintF("# Path .%.*s ", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| + } |
| #endif |
| - Module* member = factory()->NewModulePath(result, name, pos); |
| + Module* member = |
| + factory()->NewModulePath(result, name, pos); |
| result->interface()->Add(name, member->interface(), zone(), ok); |
| if (!*ok) { |
| #ifdef DEBUG |
| if (FLAG_print_interfaces) { |
| - PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray()); |
| + PrintF("PATH TYPE ERROR at '%.*s'\n", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| PrintF("result: "); |
| result->interface()->Print(); |
| PrintF("member: "); |
| member->interface()->Print(); |
| } |
| #endif |
| - ParserTraits::ReportMessage("invalid_module_path", |
| - Vector<Handle<String> >(&name, 1)); |
| + ParserTraits::ReportMessage("invalid_module_path", name); |
| return NULL; |
| } |
| result = member; |
| @@ -1333,10 +1338,13 @@ Module* Parser::ParseModuleVariable(bool* ok) { |
| // Identifier |
| int pos = peek_position(); |
| - Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| + ParserSymbolTable::Symbol* name = |
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Module variable %s ", name->ToAsciiArray()); |
| + if (FLAG_print_interface_details) { |
| + PrintF("# Module variable %.*s ", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| + } |
| #endif |
| VariableProxy* proxy = scope_->NewUnresolved( |
| factory(), name, Interface::NewModule(zone()), |
| @@ -1352,7 +1360,7 @@ Module* Parser::ParseModuleUrl(bool* ok) { |
| int pos = peek_position(); |
| Expect(Token::STRING, CHECK_OK); |
| - Handle<String> symbol = GetSymbol(); |
| + ParserSymbolTable::Symbol* symbol = GetSymbol(scanner()); |
| // TODO(ES6): Request JS resource from environment... |
| @@ -1396,9 +1404,9 @@ Block* Parser::ParseImportDeclaration(bool* ok) { |
| int pos = peek_position(); |
| Expect(Token::IMPORT, CHECK_OK); |
| - ZoneStringList names(1, zone()); |
| + ZoneList<ParserSymbolTable::Symbol*> names(1, zone()); |
| - Handle<String> name = ParseIdentifierName(CHECK_OK); |
| + ParserSymbolTable::Symbol* name = ParseIdentifierName(CHECK_OK); |
| names.Add(name, zone()); |
| while (peek() == Token::COMMA) { |
| Consume(Token::COMMA); |
| @@ -1415,21 +1423,23 @@ Block* Parser::ParseImportDeclaration(bool* ok) { |
| Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); |
| for (int i = 0; i < names.length(); ++i) { |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Import %s ", names[i]->ToAsciiArray()); |
| + if (FLAG_print_interface_details) { |
| + PrintF("# Import %.*s ", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| + } |
| #endif |
| Interface* interface = Interface::NewUnknown(zone()); |
| module->interface()->Add(names[i], interface, zone(), ok); |
| if (!*ok) { |
| #ifdef DEBUG |
| if (FLAG_print_interfaces) { |
| - PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray()); |
| + PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->literal_bytes.length(), |
| + name->literal_bytes.start()); |
| PrintF("module: "); |
| module->interface()->Print(); |
| } |
| #endif |
| - ParserTraits::ReportMessage("invalid_module_path", |
| - Vector<Handle<String> >(&name, 1)); |
| + ParserTraits::ReportMessage("invalid_module_path", name); |
| return NULL; |
| } |
| VariableProxy* proxy = NewUnresolved(names[i], LET, interface); |
| @@ -1455,14 +1465,14 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
| Expect(Token::EXPORT, CHECK_OK); |
| Statement* result = NULL; |
| - ZoneStringList names(1, zone()); |
| + ZoneList<ParserSymbolTable::Symbol*> names(1, zone()); |
| switch (peek()) { |
| case Token::IDENTIFIER: { |
| int pos = position(); |
| - Handle<String> name = |
| + ParserSymbolTable::Symbol* name = |
| ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| // Handle 'module' as a context-sensitive keyword. |
| - if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) { |
| + if (name != symbol_table_->module_string()) { |
| names.Add(name, zone()); |
| while (peek() == Token::COMMA) { |
| Consume(Token::COMMA); |
| @@ -1497,8 +1507,10 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
| Interface* interface = scope_->interface(); |
| for (int i = 0; i < names.length(); ++i) { |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Export %s ", names[i]->ToAsciiArray()); |
| + if (FLAG_print_interface_details) { |
| + PrintF("# Export %.*s ", names[i]->literal_bytes.length(), |
| + names[i]->literal_bytes.start()); |
| + } |
| #endif |
| Interface* inner = Interface::NewUnknown(zone()); |
| interface->Add(names[i], inner, zone(), CHECK_OK); |
| @@ -1518,8 +1530,8 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
| } |
| -Statement* Parser::ParseBlockElement(ZoneStringList* labels, |
| - bool* ok) { |
| +Statement* Parser::ParseBlockElement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // (Ecma 262 5th Edition, clause 14): |
| // SourceElement: |
| // Statement |
| @@ -1543,7 +1555,8 @@ Statement* Parser::ParseBlockElement(ZoneStringList* labels, |
| } |
| -Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { |
| +Statement* Parser::ParseStatement(ZoneList<ParserSymbolTable::Symbol*>* labels, |
| + bool* ok) { |
| // Statement :: |
| // Block |
| // VariableStatement |
| @@ -1637,7 +1650,8 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { |
| // Statement: |
| // GeneratorDeclaration |
| if (strict_mode() == STRICT) { |
| - ReportMessageAt(scanner()->peek_location(), "strict_function"); |
| + ParserTraits::ReportMessageAt(scanner()->peek_location(), |
| + "strict_function"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -1653,8 +1667,9 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { |
| } |
| +template<typename SymbolType> |
| VariableProxy* Parser::NewUnresolved( |
| - Handle<String> name, VariableMode mode, Interface* interface) { |
| + SymbolType name, VariableMode mode, Interface* interface) { |
| // If we are inside a function, a declaration of a var/const variable is a |
| // truly local variable, and the scope of the variable is always the function |
| // scope. |
| @@ -1667,7 +1682,8 @@ VariableProxy* Parser::NewUnresolved( |
| void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
| VariableProxy* proxy = declaration->proxy(); |
| - Handle<String> name = proxy->name(); |
| + ASSERT(proxy->raw_name() != NULL); |
| + ParserSymbolTable::Symbol* name = proxy->raw_name(); |
| VariableMode mode = declaration->mode(); |
| Scope* declaration_scope = DeclarationScope(mode); |
| Variable* var = NULL; |
| @@ -1717,10 +1733,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
| if (allow_harmony_scoping() && strict_mode() == STRICT) { |
| // In harmony we treat re-declarations as early errors. See |
| // ES5 16 for a definition of early errors. |
| - SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); |
| - const char* elms[1] = { c_string.get() }; |
| - Vector<const char*> args(elms, 1); |
| - ReportMessage("var_redeclaration", args); |
| + ParserTraits::ReportMessage("var_redeclaration", name); |
| *ok = false; |
| return; |
| } |
| @@ -1798,8 +1811,15 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
| if (FLAG_harmony_modules) { |
| bool ok; |
| #ifdef DEBUG |
| - if (FLAG_print_interface_details) |
| - PrintF("# Declare %s\n", var->name()->ToAsciiArray()); |
| + if (FLAG_print_interface_details) { |
| + if (!var->name().is_null()) { |
|
rossberg
2014/05/08 12:52:08
Why is this case needed?
marja
2014/06/03 08:48:20
Done
(It wasn't.)
|
| + PrintF("# Declare %s\n", var->name()->ToAsciiArray()); |
| + } else { |
| + ASSERT(var->raw_name() != NULL); |
| + PrintF("# Declare %.*s ", var->raw_name()->literal_bytes.length(), |
| + var->raw_name()->literal_bytes.start()); |
| + } |
| + } |
| #endif |
| proxy->interface()->Unify(var->interface(), zone(), &ok); |
| if (!ok) { |
| @@ -1812,8 +1832,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
| var->interface()->Print(); |
| } |
| #endif |
| - ParserTraits::ReportMessage("module_type_error", |
| - Vector<Handle<String> >(&name, 1)); |
| + ParserTraits::ReportMessage("module_type_error", name); |
| } |
| } |
| } |
| @@ -1828,7 +1847,8 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { |
| int pos = peek_position(); |
| Expect(Token::FUNCTION, CHECK_OK); |
| // Allow "eval" or "arguments" for backward compatibility. |
| - Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| + ParserSymbolTable::Symbol* name = |
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| Expect(Token::LPAREN, CHECK_OK); |
| bool done = (peek() == Token::RPAREN); |
| while (!done) { |
| @@ -1863,7 +1883,8 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { |
| } |
| -Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) { |
| +Statement* Parser::ParseFunctionDeclaration( |
| + ZoneList<ParserSymbolTable::Symbol*>* names, bool* ok) { |
| // FunctionDeclaration :: |
| // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| // GeneratorDeclaration :: |
| @@ -1873,7 +1894,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) { |
| int pos = position(); |
| bool is_generator = allow_generators() && Check(Token::MUL); |
| bool is_strict_reserved = false; |
| - Handle<String> name = ParseIdentifierOrStrictReservedWord( |
| + ParserSymbolTable::Symbol* name = ParseIdentifierOrStrictReservedWord( |
| &is_strict_reserved, CHECK_OK); |
| FunctionLiteral* fun = ParseFunctionLiteral(name, |
| scanner()->location(), |
| @@ -1899,7 +1920,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) { |
| } |
| -Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
| +Block* Parser::ParseBlock(ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| if (allow_harmony_scoping() && strict_mode() == STRICT) { |
| return ParseScopedBlock(labels, ok); |
| } |
| @@ -1926,7 +1947,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
| } |
| -Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { |
| +Block* Parser::ParseScopedBlock(ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // The harmony mode uses block elements instead of statements. |
| // |
| // Block :: |
| @@ -1960,13 +1981,13 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { |
| } |
| -Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
| - ZoneStringList* names, |
| - bool* ok) { |
| +Block* Parser::ParseVariableStatement( |
| + VariableDeclarationContext var_context, |
| + ZoneList<ParserSymbolTable::Symbol*>* names, bool* ok) { |
| // VariableStatement :: |
| // VariableDeclarations ';' |
| - Handle<String> ignore; |
| + ParserSymbolTable::Symbol* ignore; |
| Block* result = |
| ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK); |
| ExpectSemicolon(CHECK_OK); |
| @@ -1982,8 +2003,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
| Block* Parser::ParseVariableDeclarations( |
| VariableDeclarationContext var_context, |
| VariableDeclarationProperties* decl_props, |
| - ZoneStringList* names, |
| - Handle<String>* out, |
| + ZoneList<ParserSymbolTable::Symbol*>* names, |
| + ParserSymbolTable::Symbol** out, |
| bool* ok) { |
| // VariableDeclarations :: |
| // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] |
| @@ -2032,14 +2053,14 @@ Block* Parser::ParseVariableDeclarations( |
| if (var_context == kStatement) { |
| // In strict mode 'const' declarations are only allowed in source |
| // element positions. |
| - ReportMessage("unprotected_const", Vector<const char*>::empty()); |
| + ParserTraits::ReportMessage("unprotected_const"); |
| *ok = false; |
| return NULL; |
| } |
| mode = CONST; |
| init_op = Token::INIT_CONST; |
| } else { |
| - ReportMessage("strict_const", Vector<const char*>::empty()); |
| + ParserTraits::ReportMessage("strict_const"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2056,14 +2077,14 @@ Block* Parser::ParseVariableDeclarations( |
| // |
| // TODO(rossberg): make 'let' a legal identifier in sloppy mode. |
| if (!allow_harmony_scoping() || strict_mode() == SLOPPY) { |
| - ReportMessage("illegal_let", Vector<const char*>::empty()); |
| + ReportMessage("illegal_let"); |
| *ok = false; |
| return NULL; |
| } |
| Consume(Token::LET); |
| if (var_context == kStatement) { |
| // Let declarations are only allowed in source element positions. |
| - ReportMessage("unprotected_let", Vector<const char*>::empty()); |
| + ReportMessage("unprotected_let"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2091,7 +2112,7 @@ Block* Parser::ParseVariableDeclarations( |
| // Create new block with one expected declaration. |
| Block* block = factory()->NewBlock(NULL, 1, true, pos); |
| int nvars = 0; // the number of variables declared |
| - Handle<String> name; |
| + ParserSymbolTable::Symbol* name = NULL; |
| do { |
| if (fni_ != NULL) fni_->Enter(); |
| @@ -2123,7 +2144,7 @@ Block* Parser::ParseVariableDeclarations( |
| Declare(declaration, mode != VAR, CHECK_OK); |
| nvars++; |
| if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { |
| - ReportMessageAt(scanner()->location(), "too_many_variables"); |
| + ReportMessage("too_many_variables"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2222,7 +2243,7 @@ Block* Parser::ParseVariableDeclarations( |
| // Note that the function does different things depending on |
| // the number of arguments (1 or 2). |
| initialize = factory()->NewCallRuntime( |
| - isolate()->factory()->InitializeConstGlobal_string(), |
| + symbol_table_->initialize_const_global_string(), |
| Runtime::FunctionForId(Runtime::kHiddenInitializeConstGlobal), |
| arguments, pos); |
| } else { |
| @@ -2245,7 +2266,7 @@ Block* Parser::ParseVariableDeclarations( |
| // Note that the function does different things depending on |
| // the number of arguments (2 or 3). |
| initialize = factory()->NewCallRuntime( |
| - isolate()->factory()->InitializeVarGlobal_string(), |
| + symbol_table_->initialize_var_global_string(), |
| Runtime::FunctionForId(Runtime::kInitializeVarGlobal), |
| arguments, pos); |
| } |
| @@ -2301,19 +2322,20 @@ Block* Parser::ParseVariableDeclarations( |
| } |
| -static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) { |
| - ASSERT(!label.is_null()); |
| +static bool ContainsLabel(ZoneList<ParserSymbolTable::Symbol*>* labels, |
| + ParserSymbolTable::Symbol* label) { |
| + ASSERT(label != NULL); |
| if (labels != NULL) |
| for (int i = labels->length(); i-- > 0; ) |
| - if (labels->at(i).is_identical_to(label)) |
| + if (labels->at(i) == label) |
| return true; |
| return false; |
| } |
| -Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, |
| - bool* ok) { |
| +Statement* Parser::ParseExpressionOrLabelledStatement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // ExpressionStatement | LabelledStatement :: |
| // Expression ';' |
| // Identifier ':' Statement |
| @@ -2326,22 +2348,19 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, |
| // Expression is a single identifier, and not, e.g., a parenthesized |
| // identifier. |
| VariableProxy* var = expr->AsVariableProxy(); |
| - Handle<String> label = var->name(); |
| + ParserSymbolTable::Symbol* label = var->raw_name(); |
| // TODO(1240780): We don't check for redeclaration of labels |
| // during preparsing since keeping track of the set of active |
| // labels requires nontrivial changes to the way scopes are |
| // structured. However, these are probably changes we want to |
| // make later anyway so we should go back and fix this then. |
| if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { |
| - SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS); |
| - const char* elms[1] = { c_string.get() }; |
| - Vector<const char*> args(elms, 1); |
| - ReportMessage("label_redeclaration", args); |
| + ParserTraits::ReportMessage("label_redeclaration", label); |
| *ok = false; |
| return NULL; |
| } |
| if (labels == NULL) { |
| - labels = new(zone()) ZoneStringList(4, zone()); |
| + labels = new(zone()) ZoneList<ParserSymbolTable::Symbol*>(4, zone()); |
| } |
| labels->Add(label, zone()); |
| // Remove the "ghost" variable that turned out to be a label |
| @@ -2360,8 +2379,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, |
| !scanner()->HasAnyLineTerminatorBeforeNext() && |
| expr != NULL && |
| expr->AsVariableProxy() != NULL && |
| - String::Equals(isolate()->factory()->native_string(), |
| - expr->AsVariableProxy()->name()) && |
| + expr->AsVariableProxy()->raw_name() == symbol_table_->native_string() && |
| !scanner()->literal_contains_escapes()) { |
| return ParseNativeDeclaration(ok); |
| } |
| @@ -2372,8 +2390,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, |
| peek() != Token::IDENTIFIER || |
| scanner()->HasAnyLineTerminatorBeforeNext() || |
| expr->AsVariableProxy() == NULL || |
| - !String::Equals(isolate()->factory()->module_string(), |
| - expr->AsVariableProxy()->name()) || |
| + expr->AsVariableProxy()->raw_name() != symbol_table_->module_string() || |
| scanner()->literal_contains_escapes()) { |
| ExpectSemicolon(CHECK_OK); |
| } |
| @@ -2381,7 +2398,8 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, |
| } |
| -IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) { |
| +IfStatement* Parser::ParseIfStatement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // IfStatement :: |
| // 'if' '(' Expression ')' Statement ('else' Statement)? |
| @@ -2409,24 +2427,21 @@ Statement* Parser::ParseContinueStatement(bool* ok) { |
| int pos = peek_position(); |
| Expect(Token::CONTINUE, CHECK_OK); |
| - Handle<String> label = Handle<String>::null(); |
| + ParserSymbolTable::Symbol* label = NULL; |
| Token::Value tok = peek(); |
| if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| } |
| - IterationStatement* target = NULL; |
| - target = LookupContinueTarget(label, CHECK_OK); |
| + IterationStatement* target = LookupContinueTarget(label, CHECK_OK); |
| if (target == NULL) { |
| // Illegal continue statement. |
| - const char* message = "illegal_continue"; |
| - Vector<Handle<String> > args; |
| - if (!label.is_null()) { |
| - message = "unknown_label"; |
| - args = Vector<Handle<String> >(&label, 1); |
| + if (label != NULL) { |
| + ParserTraits::ReportMessage("unknown_label", label); |
| + } else { |
| + ParserTraits::ReportMessage("illegal_continue"); |
| } |
| - ParserTraits::ReportMessageAt(scanner()->location(), message, args); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2435,13 +2450,13 @@ Statement* Parser::ParseContinueStatement(bool* ok) { |
| } |
| -Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
| +Statement* Parser::ParseBreakStatement(ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // BreakStatement :: |
| // 'break' Identifier? ';' |
| int pos = peek_position(); |
| Expect(Token::BREAK, CHECK_OK); |
| - Handle<String> label; |
| + ParserSymbolTable::Symbol* label = NULL; |
| Token::Value tok = peek(); |
| if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| @@ -2450,7 +2465,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
| } |
| // Parse labeled break statements that target themselves into |
| // empty statements, e.g. 'l1: l2: l3: break l2;' |
| - if (!label.is_null() && ContainsLabel(labels, label)) { |
| + if (label != NULL && ContainsLabel(labels, label)) { |
| ExpectSemicolon(CHECK_OK); |
| return factory()->NewEmptyStatement(pos); |
| } |
| @@ -2458,13 +2473,11 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
| target = LookupBreakTarget(label, CHECK_OK); |
| if (target == NULL) { |
| // Illegal break statement. |
| - const char* message = "illegal_break"; |
| - Vector<Handle<String> > args; |
| - if (!label.is_null()) { |
| - message = "unknown_label"; |
| - args = Vector<Handle<String> >(&label, 1); |
| + if (label != NULL) { |
| + ParserTraits::ReportMessage("unknown_label", label); |
| + } else { |
| + ParserTraits::ReportMessage("illegal_break"); |
| } |
| - ParserTraits::ReportMessageAt(scanner()->location(), message, args); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2507,7 +2520,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) { |
| Scope* decl_scope = scope_->DeclarationScope(); |
| if (decl_scope->is_global_scope() || decl_scope->is_eval_scope()) { |
| - ReportMessageAt(loc, "illegal_return"); |
| + ParserTraits::ReportMessageAt(loc, "illegal_return"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2515,7 +2528,8 @@ Statement* Parser::ParseReturnStatement(bool* ok) { |
| } |
| -Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
| +Statement* Parser::ParseWithStatement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // WithStatement :: |
| // 'with' '(' Expression ')' Statement |
| @@ -2523,7 +2537,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
| int pos = position(); |
| if (strict_mode() == STRICT) { |
| - ReportMessage("strict_mode_with", Vector<const char*>::empty()); |
| + ReportMessage("strict_mode_with"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2556,8 +2570,7 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
| } else { |
| Expect(Token::DEFAULT, CHECK_OK); |
| if (*default_seen_ptr) { |
| - ReportMessage("multiple_defaults_in_switch", |
| - Vector<const char*>::empty()); |
| + ReportMessage("multiple_defaults_in_switch"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2578,8 +2591,8 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
| } |
| -SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels, |
| - bool* ok) { |
| +SwitchStatement* Parser::ParseSwitchStatement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // SwitchStatement :: |
| // 'switch' '(' Expression ')' '{' CaseClause* '}' |
| @@ -2613,7 +2626,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) { |
| Expect(Token::THROW, CHECK_OK); |
| int pos = position(); |
| if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
| - ReportMessage("newline_after_throw", Vector<const char*>::empty()); |
| + ReportMessage("newline_after_throw"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2649,7 +2662,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| Token::Value tok = peek(); |
| if (tok != Token::CATCH && tok != Token::FINALLY) { |
| - ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); |
| + ReportMessage("no_catch_or_finally"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2662,7 +2675,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| Scope* catch_scope = NULL; |
| Variable* catch_variable = NULL; |
| Block* catch_block = NULL; |
| - Handle<String> name; |
| + ParserSymbolTable::Symbol* name = NULL; |
| if (tok == Token::CATCH) { |
| Consume(Token::CATCH); |
| @@ -2732,8 +2745,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
| } |
| -DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, |
| - bool* ok) { |
| +DoWhileStatement* Parser::ParseDoWhileStatement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // DoStatement :: |
| // 'do' Statement 'while' '(' Expression ')' ';' |
| @@ -2760,7 +2773,8 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, |
| } |
| -WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { |
| +WhileStatement* Parser::ParseWhileStatement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // WhileStatement :: |
| // 'while' '(' Expression ')' Statement |
| @@ -2801,9 +2815,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
| if (for_of != NULL) { |
| Factory* heap_factory = isolate()->factory(); |
| Variable* iterator = scope_->DeclarationScope()->NewTemporary( |
| - heap_factory->dot_iterator_string()); |
| + symbol_table_->dot_iterator_string()); |
| Variable* result = scope_->DeclarationScope()->NewTemporary( |
| - heap_factory->dot_result_string()); |
| + symbol_table_->dot_result_string()); |
| Expression* assign_iterator; |
| Expression* next_result; |
| @@ -2861,7 +2875,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
| } |
| -Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| +Statement* Parser::ParseForStatement( |
| + ZoneList<ParserSymbolTable::Symbol*>* labels, bool* ok) { |
| // ForStatement :: |
| // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| @@ -2879,7 +2894,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| if (peek() != Token::SEMICOLON) { |
| if (peek() == Token::VAR || peek() == Token::CONST) { |
| bool is_const = peek() == Token::CONST; |
| - Handle<String> name; |
| + ParserSymbolTable::Symbol* name = NULL; |
| VariableDeclarationProperties decl_props = kHasNoInitializers; |
| Block* variable_statement = |
| ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, |
| @@ -2887,7 +2902,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| bool accept_OF = decl_props == kHasNoInitializers; |
| ForEachStatement::VisitMode mode; |
| - if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) { |
| + if (name != NULL && CheckInOrOf(accept_OF, &mode)) { |
| Interface* interface = |
| is_const ? Interface::NewConst() : Interface::NewValue(); |
| ForEachStatement* loop = |
| @@ -2915,12 +2930,12 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| init = variable_statement; |
| } |
| } else if (peek() == Token::LET) { |
| - Handle<String> name; |
| + ParserSymbolTable::Symbol* name = NULL; |
| VariableDeclarationProperties decl_props = kHasNoInitializers; |
| Block* variable_statement = |
| ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, |
| CHECK_OK); |
| - bool accept_IN = !name.is_null() && decl_props != kHasInitializers; |
| + bool accept_IN = name != NULL && decl_props != kHasInitializers; |
| bool accept_OF = decl_props == kHasNoInitializers; |
| ForEachStatement::VisitMode mode; |
| @@ -2940,14 +2955,14 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| // TODO(keuchel): Move the temporary variable to the block scope, after |
| // implementing stack allocated block scoped variables. |
| - Factory* heap_factory = isolate()->factory(); |
| - Handle<String> tempstr; |
| - ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| - isolate(), tempstr, |
| - heap_factory->NewConsString(heap_factory->dot_for_string(), name), |
| - 0); |
| - Handle<String> tempname = heap_factory->InternalizeString(tempstr); |
| - Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname); |
| + // Factory* heap_factory = isolate()->factory(); |
| + // FIXME: do this somehow independent of the heap. |
| + // ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| + // isolate(), tempstr, |
| + // heap_factory->NewConsString(heap_factory->dot_for_string(), name), |
| + // 0); |
| + Variable* temp = scope_->DeclarationScope()->NewTemporary( |
| + symbol_table_->dot_for_string()); |
| VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
| ForEachStatement* loop = |
| factory()->NewForEachStatement(mode, labels, pos); |
| @@ -3078,11 +3093,9 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { |
| } |
| -void Parser::ReportInvalidCachedData(Handle<String> name, bool* ok) { |
| - SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS); |
| - const char* element[1] = { name_string.get() }; |
| - ReportMessage("invalid_cached_data_function", |
| - Vector<const char*>(element, 1)); |
| +void Parser::ReportInvalidCachedData(ParserSymbolTable::Symbol* name, |
| + bool* ok) { |
| + ParserTraits::ReportMessage("invalid_cached_data_function", name); |
| *ok = false; |
| } |
| @@ -3131,7 +3144,7 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { |
| FunctionLiteral* Parser::ParseFunctionLiteral( |
| - Handle<String> function_name, |
| + ParserSymbolTable::Symbol* function_name, |
| Scanner::Location function_name_location, |
| bool name_is_strict_reserved, |
| bool is_generator, |
| @@ -3147,11 +3160,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| // Anonymous functions were passed either the empty symbol or a null |
| // handle as the function name. Remember if we were passed a non-empty |
| // handle to decide whether to invoke function name inference. |
| - bool should_infer_name = function_name.is_null(); |
| + bool should_infer_name = function_name == NULL; |
| // We want a non-null handle as the function name. |
| if (should_infer_name) { |
| - function_name = isolate()->factory()->empty_string(); |
| + function_name = symbol_table_->empty_string(); |
| } |
| int num_parameters = 0; |
| @@ -3215,8 +3228,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| // Calling a generator returns a generator object. That object is stored |
| // in a temporary variable, a definition that is used by "yield" |
| // expressions. This also marks the FunctionState as a generator. |
| - Variable* temp = scope_->DeclarationScope()->NewTemporary( |
| - isolate()->factory()->dot_generator_object_string()); |
| + ParserSymbolTable::Symbol* generator_name = |
| + symbol_table_->GetOneByteSymbol(Vector<const uint8_t>( |
| + reinterpret_cast<const unsigned char*>(".generator"), 10)); |
| + Variable* temp = scope_->DeclarationScope()->NewTemporary(generator_name); |
| function_state.set_generator_object_variable(temp); |
| } |
| @@ -3235,7 +3250,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| bool done = (peek() == Token::RPAREN); |
| while (!done) { |
| bool is_strict_reserved = false; |
| - Handle<String> param_name = |
| + ParserSymbolTable::Symbol* param_name = |
| ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| // Store locations for possible future error reports. |
| @@ -3253,7 +3268,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| scope_->DeclareParameter(param_name, VAR); |
| num_parameters++; |
| if (num_parameters > Code::kMaxArguments) { |
| - ReportMessageAt(scanner()->location(), "too_many_parameters"); |
| + ReportMessage("too_many_parameters"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -3273,6 +3288,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| Variable* fvar = NULL; |
| Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; |
| if (function_type == FunctionLiteral::NAMED_EXPRESSION) { |
| + ASSERT(function_name != NULL); |
| if (allow_harmony_scoping() && strict_mode() == STRICT) { |
| fvar_init_op = Token::INIT_CONST; |
| } |
| @@ -3403,7 +3419,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| } |
| -void Parser::SkipLazyFunctionBody(Handle<String> function_name, |
| +void Parser::SkipLazyFunctionBody(ParserSymbolTable::Symbol* function_name, |
| int* materialized_literal_count, |
| int* expected_property_count, |
| bool* ok) { |
| @@ -3452,14 +3468,9 @@ void Parser::SkipLazyFunctionBody(Handle<String> function_name, |
| return; |
| } |
| if (logger.has_error()) { |
| - const char* arg = logger.argument_opt(); |
| - Vector<const char*> args; |
| - if (arg != NULL) { |
| - args = Vector<const char*>(&arg, 1); |
| - } |
| ParserTraits::ReportMessageAt( |
| Scanner::Location(logger.start(), logger.end()), |
| - logger.message(), args, logger.is_reference_error()); |
| + logger.message(), logger.argument_opt(), logger.is_reference_error()); |
| *ok = false; |
| return; |
| } |
| @@ -3487,7 +3498,7 @@ void Parser::SkipLazyFunctionBody(Handle<String> function_name, |
| ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| - Handle<String> function_name, int pos, Variable* fvar, |
| + ParserSymbolTable::Symbol* function_name, int pos, Variable* fvar, |
| Token::Value fvar_init_op, bool is_generator, bool* ok) { |
| // Everything inside an eagerly parsed function will be parsed eagerly |
| // (see comment above). |
| @@ -3510,7 +3521,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| ZoneList<Expression*>* arguments = |
| new(zone()) ZoneList<Expression*>(0, zone()); |
| CallRuntime* allocation = factory()->NewCallRuntime( |
| - isolate()->factory()->empty_string(), |
| + symbol_table_->empty_string(), |
| Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject), |
| arguments, pos); |
| VariableProxy* init_proxy = factory()->NewVariableProxy( |
| @@ -3570,6 +3581,33 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
| } |
| +void Parser::CheckPendingError() { |
| + if (has_pending_error_) { |
| + MessageLocation location(script_, |
| + pending_location_.beg_pos, |
| + pending_location_.end_pos); |
| + Factory* factory = isolate()->factory(); |
| + bool has_arg = pending_arg_ != NULL || pending_char_arg_ != NULL; |
| + Handle<FixedArray> elements = |
| + factory->NewFixedArray(has_arg ? 1 : 0); |
| + if (pending_arg_ != NULL) { |
| + Handle<String> arg_string = pending_arg_->string(); |
| + elements->set(0, *arg_string); |
| + } else if (pending_char_arg_ != NULL) { |
| + Handle<String> arg_string = |
| + factory->NewStringFromUtf8(CStrVector(pending_char_arg_)) |
| + .ToHandleChecked(); |
| + elements->set(0, *arg_string); |
| + } |
| + Handle<JSArray> array = factory->NewJSArrayWithElements(elements); |
| + Handle<Object> result = pending_is_reference_error_ |
| + ? factory->NewReferenceError(pending_message_, array) |
| + : factory->NewSyntaxError(pending_message_, array); |
| + isolate()->Throw(*result, &location); |
| + } |
| +} |
| + |
| + |
| Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| // CallRuntime :: |
| // '%' Identifier Arguments |
| @@ -3577,7 +3615,8 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| int pos = peek_position(); |
| Expect(Token::MOD, CHECK_OK); |
| // Allow "eval" or "arguments" for backward compatibility. |
| - Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| + ParserSymbolTable::Symbol* name = |
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
| if (extension_ != NULL) { |
| @@ -3586,7 +3625,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| scope_->DeclarationScope()->ForceEagerCompilation(); |
| } |
| - const Runtime::Function* function = Runtime::FunctionForName(name); |
| + const Runtime::Function* function = Runtime::FunctionForName(name->string()); |
| // Check for built-in IS_VAR macro. |
| if (function != NULL && |
| @@ -3598,7 +3637,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) { |
| return args->at(0); |
| } else { |
| - ReportMessage("not_isvar", Vector<const char*>::empty()); |
| + ReportMessage("not_isvar"); |
| *ok = false; |
| return NULL; |
| } |
| @@ -3608,15 +3647,14 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| if (function != NULL && |
| function->nargs != -1 && |
| function->nargs != args->length()) { |
| - ReportMessage("illegal_access", Vector<const char*>::empty()); |
| + ReportMessage("illegal_access"); |
| *ok = false; |
| return NULL; |
| } |
| // Check that the function is defined if it's an inline runtime call. |
| - if (function == NULL && name->Get(0) == '_') { |
| - ParserTraits::ReportMessage("not_defined", |
| - Vector<Handle<String> >(&name, 1)); |
| + if (function == NULL && name->literal_bytes.at(0) == '_') { |
| + ParserTraits::ReportMessage("not_defined", name); |
| *ok = false; |
| return NULL; |
| } |
| @@ -3637,15 +3675,12 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
| if (decl != NULL) { |
| // In harmony mode we treat conflicting variable bindinds as early |
| // errors. See ES5 16 for a definition of early errors. |
| - Handle<String> name = decl->proxy()->name(); |
| - SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); |
| - const char* elms[1] = { c_string.get() }; |
| - Vector<const char*> args(elms, 1); |
| + ParserSymbolTable::Symbol* name = decl->proxy()->raw_name(); |
| int position = decl->proxy()->position(); |
| Scanner::Location location = position == RelocInfo::kNoPosition |
| ? Scanner::Location::invalid() |
| : Scanner::Location(position, position + 1); |
| - ParserTraits::ReportMessageAt(location, "var_redeclaration", args); |
| + ReportMessageAt(location, "var_redeclaration", name); |
| *ok = false; |
| } |
| } |
| @@ -3655,7 +3690,7 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
| // Parser support |
| -bool Parser::TargetStackContainsLabel(Handle<String> label) { |
| +bool Parser::TargetStackContainsLabel(ParserSymbolTable::Symbol* label) { |
| for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| BreakableStatement* stat = t->node()->AsBreakableStatement(); |
| if (stat != NULL && ContainsLabel(stat->labels(), label)) |
| @@ -3665,8 +3700,9 @@ bool Parser::TargetStackContainsLabel(Handle<String> label) { |
| } |
| -BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) { |
| - bool anonymous = label.is_null(); |
| +BreakableStatement* Parser::LookupBreakTarget(ParserSymbolTable::Symbol* label, |
| + bool* ok) { |
| + bool anonymous = label == NULL; |
| for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| BreakableStatement* stat = t->node()->AsBreakableStatement(); |
| if (stat == NULL) continue; |
| @@ -3680,9 +3716,9 @@ BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) { |
| } |
| -IterationStatement* Parser::LookupContinueTarget(Handle<String> label, |
| - bool* ok) { |
| - bool anonymous = label.is_null(); |
| +IterationStatement* Parser::LookupContinueTarget( |
| + ParserSymbolTable::Symbol* label, bool* ok) { |
| + bool anonymous = label == NULL; |
| for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| IterationStatement* stat = t->node()->AsIterationStatement(); |
| if (stat == NULL) continue; |
| @@ -4605,7 +4641,13 @@ bool RegExpParser::ParseRegExp(FlatStringReader* input, |
| bool Parser::Parse() { |
| ASSERT(info()->function() == NULL); |
| + ASSERT(info()->symbol_table() == NULL); |
| FunctionLiteral* result = NULL; |
| + symbol_table_ = new ParserSymbolTable(); |
| + if (allow_natives_syntax() || extension_ != NULL) { |
| + symbol_table_->AlwaysInternalize(isolate()); |
| + } |
| + |
| if (info()->is_lazy()) { |
| ASSERT(!info()->is_eval()); |
| if (info()->shared_info()->is_function()) { |
| @@ -4620,20 +4662,20 @@ bool Parser::Parse() { |
| ScriptData* cached_data = *(info()->cached_data()); |
| Scanner::Location loc = cached_data->MessageLocation(); |
| const char* message = cached_data->BuildMessage(); |
| - Vector<const char*> args = cached_data->BuildArgs(); |
| - ParserTraits::ReportMessageAt(loc, message, args, |
| + const char* arg = cached_data->BuildArg(); |
| + ParserTraits::ReportMessageAt(loc, message, arg, |
| cached_data->IsReferenceError()); |
| DeleteArray(message); |
| - for (int i = 0; i < args.length(); i++) { |
| - DeleteArray(args[i]); |
| - } |
| - DeleteArray(args.start()); |
| + DeleteArray(arg); |
| ASSERT(info()->isolate()->has_pending_exception()); |
| } else { |
| result = ParseProgram(); |
| } |
| } |
| info()->SetFunction(result); |
| + // info takes ownership of symbol_table_. |
| + info()->SetSymbolTable(symbol_table_); |
| + symbol_table_ = NULL; |
| return (result != NULL); |
| } |