Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(603)

Side by Side Diff: src/runtime.cc

Issue 7979001: Scope tree serialization and ScopeIterator cleanup. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 10907 matching lines...) Expand 10 before | Expand all | Expand 10 after
10918 serialized_scope_info, scope_info, 10918 serialized_scope_info, scope_info,
10919 context, block_scope)) { 10919 context, block_scope)) {
10920 return Handle<JSObject>(); 10920 return Handle<JSObject>();
10921 } 10921 }
10922 } 10922 }
10923 10923
10924 return block_scope; 10924 return block_scope;
10925 } 10925 }
10926 10926
10927 10927
10928 // Iterate over the actual scopes visible from a stack frame. All scopes are 10928 // Iterate over the actual scopes visible from a stack frame. The iteration
10929 // proceeds from the innermost visible nested scope outwards. All scopes are
10929 // backed by an actual context except the local scope, which is inserted 10930 // backed by an actual context except the local scope, which is inserted
10930 // "artifically" in the context chain. 10931 // "artificially" in the context chain.
10931 class ScopeIterator { 10932 class ScopeIterator {
10932 public: 10933 public:
10933 enum ScopeType { 10934 enum ScopeType {
Kevin Millikin (Chromium) 2011/10/05 08:43:36 Can this be the same as Scope::Type?
Steven 2011/10/06 19:09:27 Almost. The ScopeIterator so far makes a differenc
10934 ScopeTypeGlobal = 0, 10935 ScopeTypeGlobal = 0,
10935 ScopeTypeLocal, 10936 ScopeTypeLocal,
10936 ScopeTypeWith, 10937 ScopeTypeWith,
10937 ScopeTypeClosure, 10938 ScopeTypeClosure,
10938 ScopeTypeCatch, 10939 ScopeTypeCatch,
10939 ScopeTypeBlock 10940 ScopeTypeBlock
10940 }; 10941 };
10941 10942
10942 ScopeIterator(Isolate* isolate, 10943 ScopeIterator(Isolate* isolate,
10943 JavaScriptFrame* frame, 10944 JavaScriptFrame* frame,
10944 int inlined_frame_index) 10945 int inlined_frame_index)
10945 : isolate_(isolate), 10946 : isolate_(isolate),
10946 frame_(frame), 10947 frame_(frame),
10947 inlined_frame_index_(inlined_frame_index), 10948 inlined_frame_index_(inlined_frame_index),
10948 function_(JSFunction::cast(frame->function())), 10949 function_(JSFunction::cast(frame->function())),
10949 context_(Context::cast(frame->context())), 10950 context_(Context::cast(frame->context())),
10950 local_done_(false), 10951 nested_scope_chain_(4) {
10951 at_local_(false) {
10952 10952
10953 // Check whether the first scope is actually a local scope. 10953 Handle<SerializedScopeInfo> scope_info(function_->shared()->scope_info());
10954 // If there is a stack slot for .result then this local scope has been 10954 int statement_position =
10955 // created for evaluating top level code and it is not a real local scope. 10955 function_->shared()->code()->SourceStatementPosition(frame_->pc());
10956 // Checking for the existence of .result seems fragile, but the scope info 10956 scope_info->GetNestedScopeChain(&nested_scope_chain_, statement_position);
10957 // saved with the code object does not otherwise have that information.
10958 int index = function_->shared()->scope_info()->
10959 StackSlotIndex(isolate_->heap()->result_symbol());
10960 if (index >= 0) {
10961 local_done_ = true;
10962 } else if (context_->IsGlobalContext() ||
10963 context_->IsFunctionContext()) {
10964 at_local_ = true;
10965 } else if (context_->closure() != *function_) {
10966 // The context_ is a block or with or catch block from the outer function.
10967 ASSERT(context_->IsWithContext() ||
10968 context_->IsCatchContext() ||
10969 context_->IsBlockContext());
10970 at_local_ = true;
10971 }
10972 } 10957 }
10973 10958
10974 // More scopes? 10959 // More scopes?
10975 bool Done() { return context_.is_null(); } 10960 bool Done() { return context_.is_null(); }
10976 10961
10977 // Move to the next scope. 10962 // Move to the next scope.
10978 void Next() { 10963 void Next() {
10979 // If at a local scope mark the local scope as passed. 10964 ScopeType scope_type = Type();
10980 if (at_local_) { 10965 if (scope_type == ScopeTypeGlobal) {
10981 at_local_ = false; 10966 // The global scope is always the last in the chain.
10982 local_done_ = true; 10967 ASSERT(context_->IsGlobalContext());
10983
10984 // If the current context is not associated with the local scope the
10985 // current context is the next real scope, so don't move to the next
10986 // context in this case.
10987 if (context_->closure() != *function_) {
10988 return;
10989 }
10990 }
10991
10992 // The global scope is always the last in the chain.
10993 if (context_->IsGlobalContext()) {
10994 context_ = Handle<Context>(); 10968 context_ = Handle<Context>();
10995 return; 10969 return;
10996 } 10970 }
10997 10971 if (nested_scope_chain_.is_empty()) {
10998 // Move to the next context. 10972 context_ = Handle<Context>(context_->previous(), isolate_);
10999 context_ = Handle<Context>(context_->previous(), isolate_); 10973 } else {
11000 10974 if (nested_scope_chain_.last()->HasContext()) {
11001 // If passing the local scope indicate that the current scope is now the 10975 context_ = Handle<Context>(context_->previous(), isolate_);
11002 // local scope. 10976 }
11003 if (!local_done_ && 10977 nested_scope_chain_.RemoveLast();
11004 (context_->IsGlobalContext() || context_->IsFunctionContext())) {
11005 at_local_ = true;
11006 } 10978 }
11007 } 10979 }
11008 10980
11009 // Return the type of the current scope. 10981 // Return the type of the current scope.
11010 ScopeType Type() { 10982 ScopeType Type() {
11011 if (at_local_) { 10983 if (!nested_scope_chain_.is_empty()) {
11012 return ScopeTypeLocal; 10984 Handle<SerializedScopeInfo> scope_info = nested_scope_chain_.last();
10985 switch (scope_info->ScopeType()) {
10986 case Scope::FUNCTION_SCOPE:
10987 ASSERT(context_->IsFunctionContext() ||
10988 !scope_info->HasContext());
10989 return ScopeTypeLocal;
10990 case Scope::GLOBAL_SCOPE:
10991 ASSERT(context_->IsGlobalContext());
10992 return ScopeTypeGlobal;
10993 case Scope::WITH_SCOPE:
10994 ASSERT(context_->IsWithContext());
10995 return ScopeTypeWith;
10996 case Scope::CATCH_SCOPE:
10997 ASSERT(context_->IsCatchContext());
10998 return ScopeTypeCatch;
10999 case Scope::BLOCK_SCOPE:
11000 ASSERT(!scope_info->HasContext() ||
11001 context_->IsBlockContext());
11002 return ScopeTypeBlock;
11003 case Scope::EVAL_SCOPE:
11004 UNREACHABLE();
11005 }
11013 } 11006 }
11014 if (context_->IsGlobalContext()) { 11007 if (context_->IsGlobalContext()) {
11015 ASSERT(context_->global()->IsGlobalObject()); 11008 ASSERT(context_->global()->IsGlobalObject());
11016 return ScopeTypeGlobal; 11009 return ScopeTypeGlobal;
11017 } 11010 }
11018 if (context_->IsFunctionContext()) { 11011 if (context_->IsFunctionContext()) {
11019 return ScopeTypeClosure; 11012 return ScopeTypeClosure;
11020 } 11013 }
11021 if (context_->IsCatchContext()) { 11014 if (context_->IsCatchContext()) {
11022 return ScopeTypeCatch; 11015 return ScopeTypeCatch;
11023 } 11016 }
11024 if (context_->IsBlockContext()) { 11017 if (context_->IsBlockContext()) {
11025 return ScopeTypeBlock; 11018 return ScopeTypeBlock;
11026 } 11019 }
11027 ASSERT(context_->IsWithContext()); 11020 ASSERT(context_->IsWithContext());
11028 return ScopeTypeWith; 11021 return ScopeTypeWith;
11029 } 11022 }
11030 11023
11031 // Return the JavaScript object with the content of the current scope. 11024 // Return the JavaScript object with the content of the current scope.
11032 Handle<JSObject> ScopeObject() { 11025 Handle<JSObject> ScopeObject() {
11033 switch (Type()) { 11026 switch (Type()) {
11034 case ScopeIterator::ScopeTypeGlobal: 11027 case ScopeIterator::ScopeTypeGlobal:
11035 return Handle<JSObject>(CurrentContext()->global()); 11028 return Handle<JSObject>(CurrentContext()->global());
11036 case ScopeIterator::ScopeTypeLocal: 11029 case ScopeIterator::ScopeTypeLocal:
11037 // Materialize the content of the local scope into a JSObject. 11030 // Materialize the content of the local scope into a JSObject.
11031 ASSERT(nested_scope_chain_.length() == 1);
11038 return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_); 11032 return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
11039 case ScopeIterator::ScopeTypeWith: 11033 case ScopeIterator::ScopeTypeWith:
11040 // Return the with object. 11034 // Return the with object.
11041 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); 11035 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11042 case ScopeIterator::ScopeTypeCatch: 11036 case ScopeIterator::ScopeTypeCatch:
11043 return MaterializeCatchScope(isolate_, CurrentContext()); 11037 return MaterializeCatchScope(isolate_, CurrentContext());
11044 case ScopeIterator::ScopeTypeClosure: 11038 case ScopeIterator::ScopeTypeClosure:
11045 // Materialize the content of the closure scope into a JSObject. 11039 // Materialize the content of the closure scope into a JSObject.
11046 return MaterializeClosure(isolate_, CurrentContext()); 11040 return MaterializeClosure(isolate_, CurrentContext());
11047 case ScopeIterator::ScopeTypeBlock: 11041 case ScopeIterator::ScopeTypeBlock:
11048 return MaterializeBlockScope(isolate_, CurrentContext()); 11042 return MaterializeBlockScope(isolate_, CurrentContext());
11049 } 11043 }
11050 UNREACHABLE(); 11044 UNREACHABLE();
11051 return Handle<JSObject>(); 11045 return Handle<JSObject>();
11052 } 11046 }
11053 11047
11048 Handle<SerializedScopeInfo> CurrentScopeInfo() {
11049 if (!nested_scope_chain_.is_empty()) {
11050 return nested_scope_chain_.last();
11051 } else if (context_->IsBlockContext()) {
11052 return Handle<SerializedScopeInfo>(
11053 SerializedScopeInfo::cast(context_->extension()));
11054 } else if (context_->IsFunctionContext()) {
11055 return Handle<SerializedScopeInfo>(
11056 context_->closure()->shared()->scope_info());
11057 }
11058 return Handle<SerializedScopeInfo>::null();
11059 }
11060
11054 // Return the context for this scope. For the local context there might not 11061 // Return the context for this scope. For the local context there might not
11055 // be an actual context. 11062 // be an actual context.
11056 Handle<Context> CurrentContext() { 11063 Handle<Context> CurrentContext() {
11057 if (at_local_ && context_->closure() != *function_) { 11064 if (Type() == ScopeTypeGlobal ||
11065 nested_scope_chain_.is_empty()) {
11066 return context_;
11067 } else if (nested_scope_chain_.last()->HasContext()) {
11068 return context_;
11069 } else {
11058 return Handle<Context>(); 11070 return Handle<Context>();
11059 } 11071 }
11060 return context_;
11061 } 11072 }
11062 11073
11063 #ifdef DEBUG 11074 #ifdef DEBUG
11064 // Debug print of the content of the current scope. 11075 // Debug print of the content of the current scope.
11065 void DebugPrint() { 11076 void DebugPrint() {
11066 switch (Type()) { 11077 switch (Type()) {
11067 case ScopeIterator::ScopeTypeGlobal: 11078 case ScopeIterator::ScopeTypeGlobal:
11068 PrintF("Global:\n"); 11079 PrintF("Global:\n");
11069 CurrentContext()->Print(); 11080 CurrentContext()->Print();
11070 break; 11081 break;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
11113 PrintF("\n"); 11124 PrintF("\n");
11114 } 11125 }
11115 #endif 11126 #endif
11116 11127
11117 private: 11128 private:
11118 Isolate* isolate_; 11129 Isolate* isolate_;
11119 JavaScriptFrame* frame_; 11130 JavaScriptFrame* frame_;
11120 int inlined_frame_index_; 11131 int inlined_frame_index_;
11121 Handle<JSFunction> function_; 11132 Handle<JSFunction> function_;
11122 Handle<Context> context_; 11133 Handle<Context> context_;
11123 bool local_done_; 11134 List<Handle<SerializedScopeInfo> > nested_scope_chain_;
11124 bool at_local_;
11125 11135
11126 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); 11136 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11127 }; 11137 };
11128 11138
11129 11139
11130 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) { 11140 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11131 HandleScope scope(isolate); 11141 HandleScope scope(isolate);
11132 ASSERT(args.length() == 2); 11142 ASSERT(args.length() == 2);
11133 11143
11134 // Check arguments. 11144 // Check arguments.
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
11577 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) { 11587 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
11578 HandleScope scope(isolate); 11588 HandleScope scope(isolate);
11579 ASSERT(args.length() == 0); 11589 ASSERT(args.length() == 0);
11580 isolate->debug()->ClearStepping(); 11590 isolate->debug()->ClearStepping();
11581 return isolate->heap()->undefined_value(); 11591 return isolate->heap()->undefined_value();
11582 } 11592 }
11583 11593
11584 11594
11585 // Creates a copy of the with context chain. The copy of the context chain is 11595 // Creates a copy of the with context chain. The copy of the context chain is
11586 // is linked to the function context supplied. 11596 // is linked to the function context supplied.
11587 static Handle<Context> CopyWithContextChain(Isolate* isolate, 11597 static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
11588 Handle<JSFunction> function, 11598 Handle<JSFunction> function,
11589 Handle<Context> current, 11599 Handle<Context> base,
11590 Handle<Context> base) { 11600 JavaScriptFrame* frame,
11591 // At the end of the chain. Return the base context to link to. 11601 int inlined_frame_index) {
11592 if (current->IsFunctionContext() || current->IsGlobalContext()) { 11602 HandleScope scope(isolate);
11593 return base; 11603 List<Handle<SerializedScopeInfo> > scope_chain;
11604 List<Handle<Context> > context_chain;
11605
11606 ScopeIterator it(isolate, frame, inlined_frame_index);
11607 for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
11608 it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
11609 ASSERT(!it.Done());
11610 scope_chain.Add(it.CurrentScopeInfo());
11611 context_chain.Add(it.CurrentContext());
11594 } 11612 }
11595 11613
11596 // Recursively copy the with and catch contexts. 11614 // At the end of the chain. Return the base context to link to.
11597 HandleScope scope(isolate); 11615 Handle<Context> context = base;
11598 Handle<Context> previous(current->previous()); 11616
11599 Handle<Context> new_previous = 11617 // Iteratively copy and or materialize the nested contexts.
11600 CopyWithContextChain(isolate, function, previous, base); 11618 while (!scope_chain.is_empty()) {
11601 Handle<Context> new_current; 11619 Handle<SerializedScopeInfo> scope_info = scope_chain.RemoveLast();
11602 if (current->IsCatchContext()) { 11620 Handle<Context> current = context_chain.RemoveLast();
11603 Handle<String> name(String::cast(current->extension())); 11621 ASSERT(!(scope_info->HasContext() & current.is_null()));
11604 Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX)); 11622
11605 new_current = 11623 if (scope_info->ScopeType() == Scope::CATCH_SCOPE) {
11606 isolate->factory()->NewCatchContext(function, 11624 Handle<String> name(String::cast(current->extension()));
11607 new_previous, 11625 Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX));
11608 name, 11626 context =
11609 thrown_object); 11627 isolate->factory()->NewCatchContext(function,
11610 } else if (current->IsBlockContext()) { 11628 context,
11611 Handle<SerializedScopeInfo> scope_info( 11629 name,
11612 SerializedScopeInfo::cast(current->extension())); 11630 thrown_object);
11613 new_current = 11631 } else if (scope_info->ScopeType() == Scope::BLOCK_SCOPE) {
11614 isolate->factory()->NewBlockContext(function, new_previous, scope_info); 11632 // Materialize the contents of the block scope into a JSObject.
11615 // Copy context slots. 11633 Handle<JSObject> block_scope_object =
11616 int num_context_slots = scope_info->NumberOfContextSlots(); 11634 MaterializeBlockScope(isolate, current);
11617 for (int i = Context::MIN_CONTEXT_SLOTS; i < num_context_slots; ++i) { 11635 if (block_scope_object.is_null()) {
11618 new_current->set(i, current->get(i)); 11636 return Handle<Context>::null();
11637 }
11638 // Allocate a new function context for the debug evaluation and set the
11639 // extension object.
11640 Handle<Context> new_context =
11641 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11642 function);
11643 new_context->set_extension(*block_scope_object);
11644 new_context->set_previous(*context);
11645 context = new_context;
11646 } else {
11647 ASSERT(scope_info->ScopeType() == Scope::WITH_SCOPE);
11648 ASSERT(current->IsWithContext());
11649 Handle<JSObject> extension(JSObject::cast(current->extension()));
11650 context =
11651 isolate->factory()->NewWithContext(function, context, extension);
11619 } 11652 }
11620 } else {
11621 ASSERT(current->IsWithContext());
11622 Handle<JSObject> extension(JSObject::cast(current->extension()));
11623 new_current =
11624 isolate->factory()->NewWithContext(function, new_previous, extension);
11625 } 11653 }
11626 return scope.CloseAndEscape(new_current); 11654
11655 return scope.CloseAndEscape(context);
11627 } 11656 }
11628 11657
11629 11658
11630 // Helper function to find or create the arguments object for 11659 // Helper function to find or create the arguments object for
11631 // Runtime_DebugEvaluate. 11660 // Runtime_DebugEvaluate.
11632 static Handle<Object> GetArgumentsObject(Isolate* isolate, 11661 static Handle<Object> GetArgumentsObject(Isolate* isolate,
11633 JavaScriptFrame* frame, 11662 JavaScriptFrame* frame,
11634 int inlined_frame_index, 11663 int inlined_frame_index,
11635 Handle<JSFunction> function, 11664 Handle<JSFunction> function,
11636 Handle<SerializedScopeInfo> scope_info, 11665 Handle<SerializedScopeInfo> scope_info,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
11754 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, 11783 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11755 go_between); 11784 go_between);
11756 context->set_extension(*local_scope); 11785 context->set_extension(*local_scope);
11757 // Copy any with contexts present and chain them in front of this context. 11786 // Copy any with contexts present and chain them in front of this context.
11758 Handle<Context> frame_context(Context::cast(frame->context())); 11787 Handle<Context> frame_context(Context::cast(frame->context()));
11759 Handle<Context> function_context; 11788 Handle<Context> function_context;
11760 // Get the function's context if it has one. 11789 // Get the function's context if it has one.
11761 if (scope_info->HasHeapAllocatedLocals()) { 11790 if (scope_info->HasHeapAllocatedLocals()) {
11762 function_context = Handle<Context>(frame_context->declaration_context()); 11791 function_context = Handle<Context>(frame_context->declaration_context());
11763 } 11792 }
11764 context = CopyWithContextChain(isolate, go_between, frame_context, context); 11793 context = CopyNestedScopeContextChain(isolate,
11794 go_between,
11795 context,
11796 frame,
11797 inlined_frame_index);
11765 11798
11766 if (additional_context->IsJSObject()) { 11799 if (additional_context->IsJSObject()) {
11767 Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); 11800 Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
11768 context = 11801 context =
11769 isolate->factory()->NewWithContext(go_between, context, extension); 11802 isolate->factory()->NewWithContext(go_between, context, extension);
11770 } 11803 }
11771 11804
11772 // Wrap the evaluation statement in a new function compiled in the newly 11805 // Wrap the evaluation statement in a new function compiled in the newly
11773 // created context. The function has one parameter which has to be called 11806 // created context. The function has one parameter which has to be called
11774 // 'arguments'. This it to have access to what would have been 'arguments' in 11807 // 'arguments'. This it to have access to what would have been 'arguments' in
(...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after
13196 } else { 13229 } else {
13197 // Handle last resort GC and make sure to allow future allocations 13230 // Handle last resort GC and make sure to allow future allocations
13198 // to grow the heap without causing GCs (if possible). 13231 // to grow the heap without causing GCs (if possible).
13199 isolate->counters()->gc_last_resort_from_js()->Increment(); 13232 isolate->counters()->gc_last_resort_from_js()->Increment();
13200 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); 13233 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
13201 } 13234 }
13202 } 13235 }
13203 13236
13204 13237
13205 } } // namespace v8::internal 13238 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698