From: keuchel@chromium.org Date: Tue, 18 Oct 2011 08:46:46 +0000 (+0000) Subject: Scope tree serialization and ScopeIterator cleanup. X-Git-Tag: upstream/4.7.83~18186 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4e5643a64895b30971cc668aed8882c7147fc2ca;p=platform%2Fupstream%2Fv8.git Scope tree serialization and ScopeIterator cleanup. The intention is to store enough scope information for the debugger to handle stack allocation of block scoped variables introduced by http://codereview.chromium.org/7860045/ . This CL is based on http://codereview.chromium.org/7904008/ . Review URL: http://codereview.chromium.org/7979001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9673 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/ast-inl.h b/src/ast-inl.h index 731ad2ff3..a3af2596a 100644 --- a/src/ast-inl.h +++ b/src/ast-inl.h @@ -111,6 +111,16 @@ ForInStatement::ForInStatement(Isolate* isolate, ZoneStringList* labels) } +int FunctionLiteral::start_position() const { + return scope()->start_position(); +} + + +int FunctionLiteral::end_position() const { + return scope()->end_position(); +} + + bool FunctionLiteral::strict_mode() const { return scope()->is_strict_mode(); } diff --git a/src/ast.h b/src/ast.h index 2ae1364d3..cb7763bfd 100644 --- a/src/ast.h +++ b/src/ast.h @@ -1617,8 +1617,6 @@ class FunctionLiteral: public Expression { bool has_only_simple_this_property_assignments, Handle this_property_assignments, int num_parameters, - int start_position, - int end_position, Type type, bool has_duplicate_parameters) : Expression(isolate), @@ -1631,8 +1629,6 @@ class FunctionLiteral: public Expression { has_only_simple_this_property_assignments), this_property_assignments_(this_property_assignments), num_parameters_(num_parameters), - start_position_(start_position), - end_position_(end_position), function_token_position_(RelocInfo::kNoPosition), inferred_name_(HEAP->empty_string()), is_expression_(type != DECLARATION), @@ -1648,8 +1644,8 @@ class FunctionLiteral: public Expression { ZoneList* body() const { return body_; } void set_function_token_position(int pos) { function_token_position_ = pos; } int function_token_position() const { return function_token_position_; } - int start_position() const { return start_position_; } - int end_position() const { return end_position_; } + int start_position() const; + int end_position() const; bool is_expression() const { return is_expression_; } bool is_anonymous() const { return is_anonymous_; } bool strict_mode() const; diff --git a/src/contexts.h b/src/contexts.h index ba5ee8731..fe0e22ef5 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -194,7 +194,8 @@ class Context: public FixedArray { PREVIOUS_INDEX, // The extension slot is used for either the global object (in global // contexts), eval extension object (function contexts), subject of with - // (with contexts), or the variable name (catch contexts). + // (with contexts), or the variable name (catch contexts), the serialized + // scope info (block contexts). EXTENSION_INDEX, GLOBAL_INDEX, MIN_CONTEXT_SLOTS, diff --git a/src/objects.h b/src/objects.h index fd5dc4a70..1a42811ad 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3020,6 +3020,9 @@ class SerializedScopeInfo : public FixedArray { return reinterpret_cast(object); } + // Return the type of this scope. + ScopeType Type(); + // Does this scope call eval? bool CallsEval(); @@ -3035,6 +3038,9 @@ class SerializedScopeInfo : public FixedArray { // Return if this has context slots besides MIN_CONTEXT_SLOTS; bool HasHeapAllocatedLocals(); + // Return if contexts are allocated for this scope. + bool HasContext(); + // Lookup support for serialized scope info. Returns the // the stack slot index for a given slot name if the slot is // present; otherwise returns a value < 0. The name must be a symbol diff --git a/src/parser.cc b/src/parser.cc index edd2e531d..b272fa9e0 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -407,7 +407,7 @@ unsigned* ScriptDataImpl::ReadAddress(int position) { } -Scope* Parser::NewScope(Scope* parent, Scope::Type type) { +Scope* Parser::NewScope(Scope* parent, ScopeType type) { Scope* result = new(zone()) Scope(parent, type); result->Initialize(); return result; @@ -643,14 +643,13 @@ FunctionLiteral* Parser::DoParseProgram(Handle source, mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY; if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY; - Scope::Type type = - in_global_context - ? Scope::GLOBAL_SCOPE - : Scope::EVAL_SCOPE; + ScopeType type = in_global_context ? GLOBAL_SCOPE : EVAL_SCOPE; Handle no_name = isolate()->factory()->empty_symbol(); FunctionLiteral* result = NULL; { Scope* scope = NewScope(top_scope_, type); + scope->set_start_position(0); + scope->set_end_position(source->length()); LexicalScope lexical_scope(this, scope, isolate()); if (strict_mode == kStrictMode) { top_scope_->EnableStrictMode(); @@ -678,8 +677,6 @@ FunctionLiteral* Parser::DoParseProgram(Handle source, lexical_scope.only_simple_this_property_assignments(), lexical_scope.this_property_assignments(), 0, - 0, - source->length(), FunctionLiteral::ANONYMOUS_EXPRESSION, false); // Does not have duplicate parameters. } else if (stack_overflow_) { @@ -740,7 +737,7 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, { // Parse the function literal. - Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE); + Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); if (!info->closure().is_null()) { scope = Scope::DeserializeScopeChain(info, scope); } @@ -1595,13 +1592,14 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { // Construct block expecting 16 statements. Block* body = new(zone()) Block(isolate(), labels, 16, false); - Scope* block_scope = NewScope(top_scope_, Scope::BLOCK_SCOPE); + Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE); if (top_scope_->is_strict_mode()) { block_scope->EnableStrictMode(); } // Parse the statements and collect escaping labels. Expect(Token::LBRACE, CHECK_OK); + block_scope->set_start_position(scanner().location().beg_pos); { SaveScope save_scope(this, block_scope); TargetCollector collector; Target target(&this->target_stack_, &collector); @@ -1617,7 +1615,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { } } Expect(Token::RBRACE, CHECK_OK); - + block_scope->set_end_position(scanner().location().end_pos); block_scope = block_scope->FinalizeBlockScope(); body->set_block_scope(block_scope); return body; @@ -2114,10 +2112,12 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { Expect(Token::RPAREN, CHECK_OK); top_scope_->DeclarationScope()->RecordWithStatement(); - Scope* with_scope = NewScope(top_scope_, Scope::WITH_SCOPE); + Scope* with_scope = NewScope(top_scope_, WITH_SCOPE); Statement* stmt; { SaveScope save_scope(this, with_scope); + with_scope->set_start_position(scanner().peek_location().beg_pos); stmt = ParseStatement(labels, CHECK_OK); + with_scope->set_end_position(scanner().location().end_pos); } return new(zone()) WithStatement(expr, stmt); } @@ -2243,6 +2243,11 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { Consume(Token::CATCH); Expect(Token::LPAREN, CHECK_OK); + catch_scope = NewScope(top_scope_, CATCH_SCOPE); + if (top_scope_->is_strict_mode()) { + catch_scope->EnableStrictMode(); + } + catch_scope->set_start_position(scanner().location().beg_pos); name = ParseIdentifier(CHECK_OK); if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { @@ -2255,10 +2260,6 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { if (peek() == Token::LBRACE) { Target target(&this->target_stack_, &catch_collector); - catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE); - if (top_scope_->is_strict_mode()) { - catch_scope->EnableStrictMode(); - } VariableMode mode = harmony_scoping_ ? LET : VAR; catch_variable = catch_scope->DeclareLocal(name, mode); @@ -2267,7 +2268,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { } else { Expect(Token::LBRACE, CHECK_OK); } - + catch_scope->set_end_position(scanner().location().end_pos); tok = peek(); } @@ -2375,7 +2376,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { // Create an in-between scope for let-bound iteration variables. Scope* saved_scope = top_scope_; - Scope* for_scope = NewScope(top_scope_, Scope::BLOCK_SCOPE); + Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE); if (top_scope_->is_strict_mode()) { for_scope->EnableStrictMode(); } @@ -2383,6 +2384,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { Expect(Token::FOR, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); + for_scope->set_start_position(scanner().location().beg_pos); if (peek() != Token::SEMICOLON) { if (peek() == Token::VAR || peek() == Token::CONST) { Handle name; @@ -2404,6 +2406,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { result->AddStatement(variable_statement); result->AddStatement(loop); top_scope_ = saved_scope; + for_scope->set_end_position(scanner().location().end_pos); for_scope = for_scope->FinalizeBlockScope(); ASSERT(for_scope == NULL); // Parsed for-in loop w/ variable/const declaration. @@ -2460,6 +2463,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { body_block->AddStatement(body); loop->Initialize(temp_proxy, enumerable, body_block); top_scope_ = saved_scope; + for_scope->set_end_position(scanner().location().end_pos); for_scope = for_scope->FinalizeBlockScope(); body_block->set_block_scope(for_scope); // Parsed for-in loop w/ let declaration. @@ -2490,6 +2494,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { Statement* body = ParseStatement(NULL, CHECK_OK); if (loop) loop->Initialize(expression, enumerable, body); top_scope_ = saved_scope; + for_scope->set_end_position(scanner().location().end_pos); for_scope = for_scope->FinalizeBlockScope(); ASSERT(for_scope == NULL); // Parsed for-in loop. @@ -2523,6 +2528,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { Statement* body = ParseStatement(NULL, CHECK_OK); top_scope_ = saved_scope; + for_scope->set_end_position(scanner().location().end_pos); for_scope = for_scope->FinalizeBlockScope(); if (for_scope != NULL) { // Rewrite a for statement of the form @@ -3812,15 +3818,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle function_name, // Function declarations are function scoped in normal mode, so they are // hoisted. In harmony block scoping mode they are block scoped, so they // are not hoisted. - Scope* scope = (type == FunctionLiteral::DECLARATION && - !harmony_scoping_) - ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE) - : NewScope(top_scope_, Scope::FUNCTION_SCOPE); + Scope* scope = (type == FunctionLiteral::DECLARATION && !harmony_scoping_) + ? NewScope(top_scope_->DeclarationScope(), FUNCTION_SCOPE) + : NewScope(top_scope_, FUNCTION_SCOPE); ZoneList* body = new(zone()) ZoneList(8); int materialized_literal_count; int expected_property_count; - int start_pos; - int end_pos; bool only_simple_this_property_assignments; Handle this_property_assignments; bool has_duplicate_parameters = false; @@ -3831,7 +3834,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle function_name, // FormalParameterList :: // '(' (Identifier)*[','] ')' Expect(Token::LPAREN, CHECK_OK); - start_pos = scanner().location().beg_pos; + scope->set_start_position(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(); @@ -3906,15 +3909,15 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle function_name, // compile after all. is_lazily_compiled = false; } else { - end_pos = entry.end_pos(); - if (end_pos <= function_block_pos) { + scope->set_end_position(entry.end_pos()); + if (scope->end_position() <= function_block_pos) { // End position greater than end of stream is safe, and hard to check. ReportInvalidPreparseData(function_name, CHECK_OK); } isolate()->counters()->total_preparse_skipped()->Increment( - end_pos - function_block_pos); + scope->end_position() - function_block_pos); // Seek to position just before terminal '}'. - scanner().SeekForward(end_pos - 1); + scanner().SeekForward(scope->end_position() - 1); materialized_literal_count = entry.literal_count(); expected_property_count = entry.property_count(); if (entry.strict_mode()) top_scope_->EnableStrictMode(); @@ -3934,12 +3937,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle function_name, this_property_assignments = lexical_scope.this_property_assignments(); Expect(Token::RBRACE, CHECK_OK); - end_pos = scanner().location().end_pos; + scope->set_end_position(scanner().location().end_pos); } // Validate strict mode. if (top_scope_->is_strict_mode()) { if (IsEvalOrArguments(function_name)) { + int start_pos = scope->start_position(); int position = function_token_position != RelocInfo::kNoPosition ? function_token_position : (start_pos > 0 ? start_pos - 1 : start_pos); @@ -3962,6 +3966,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle function_name, return NULL; } if (name_is_strict_reserved) { + int start_pos = scope->start_position(); int position = function_token_position != RelocInfo::kNoPosition ? function_token_position : (start_pos > 0 ? start_pos - 1 : start_pos); @@ -3977,7 +3982,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle function_name, *ok = false; return NULL; } - CheckOctalLiteral(start_pos, end_pos, CHECK_OK); + CheckOctalLiteral(scope->start_position(), + scope->end_position(), + CHECK_OK); } } @@ -3995,8 +4002,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle function_name, only_simple_this_property_assignments, this_property_assignments, num_parameters, - start_pos, - end_pos, type, has_duplicate_parameters); function_literal->set_function_token_position(function_token_position); diff --git a/src/parser.h b/src/parser.h index 8db44bee8..5c53cf8c8 100644 --- a/src/parser.h +++ b/src/parser.h @@ -678,7 +678,7 @@ class Parser { return ∅ } - Scope* NewScope(Scope* parent, Scope::Type type); + Scope* NewScope(Scope* parent, ScopeType type); Handle LookupSymbol(int symbol_id); diff --git a/src/runtime.cc b/src/runtime.cc index e614103b4..eb1385c90 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -11068,9 +11068,10 @@ static Handle MaterializeBlockScope( } -// Iterate over the actual scopes visible from a stack frame. All scopes are +// Iterate over the actual scopes visible from a stack frame. The iteration +// proceeds from the innermost visible nested scope outwards. All scopes are // backed by an actual context except the local scope, which is inserted -// "artifically" in the context chain. +// "artificially" in the context chain. class ScopeIterator { public: enum ScopeType { @@ -11090,28 +11091,44 @@ class ScopeIterator { inlined_frame_index_(inlined_frame_index), function_(JSFunction::cast(frame->function())), context_(Context::cast(frame->context())), - local_done_(false), - at_local_(false) { + nested_scope_chain_(4) { - // Check whether the first scope is actually a local scope. - // If there is a stack slot for .result then this local scope has been - // created for evaluating top level code and it is not a real local scope. + // Check whether we are in global code or function code. If there is a stack + // slot for .result then this function has been created for evaluating + // global code and it is not a real function. // Checking for the existence of .result seems fragile, but the scope info // saved with the code object does not otherwise have that information. int index = function_->shared()->scope_info()-> StackSlotIndex(isolate_->heap()->result_symbol()); + + // Reparse the code and analyze the scopes. + ZoneScope zone_scope(isolate, DELETE_ON_EXIT); + Handle shared_info(function_->shared()); + Handle