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

Side by Side Diff: src/scopes.cc

Issue 7890031: Mark variables as being accessed from any inner scope, not only function scopes (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
« no previous file with comments | « no previous file | src/variables.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 } 688 }
689 689
690 690
691 static void PrintVar(int indent, Variable* var) { 691 static void PrintVar(int indent, Variable* var) {
692 if (var->is_used() || !var->IsUnallocated()) { 692 if (var->is_used() || !var->IsUnallocated()) {
693 Indent(indent, Variable::Mode2String(var->mode())); 693 Indent(indent, Variable::Mode2String(var->mode()));
694 PrintF(" "); 694 PrintF(" ");
695 PrintName(var->name()); 695 PrintName(var->name());
696 PrintF("; // "); 696 PrintF("; // ");
697 PrintLocation(var); 697 PrintLocation(var);
698 if (var->is_accessed_from_inner_function_scope()) { 698 if (var->is_accessed_from_inner_scope()) {
699 if (!var->IsUnallocated()) PrintF(", "); 699 if (!var->IsUnallocated()) PrintF(", ");
700 PrintF("inner scope access"); 700 PrintF("inner scope access");
701 } 701 }
702 PrintF("\n"); 702 PrintF("\n");
703 } 703 }
704 } 704 }
705 705
706 706
707 static void PrintMap(int indent, VariableMap* map) { 707 static void PrintMap(int indent, VariableMap* map) {
708 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { 708 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 } 811 }
812 812
813 813
814 // Lookup a variable starting with this scope. The result is either 814 // Lookup a variable starting with this scope. The result is either
815 // the statically resolved variable belonging to an outer scope, or 815 // the statically resolved variable belonging to an outer scope, or
816 // NULL. It may be NULL because a) we couldn't find a variable, or b) 816 // NULL. It may be NULL because a) we couldn't find a variable, or b)
817 // because the variable is just a guess (and may be shadowed by 817 // because the variable is just a guess (and may be shadowed by
818 // another variable that is introduced dynamically via an 'eval' call 818 // another variable that is introduced dynamically via an 'eval' call
819 // or a 'with' statement). 819 // or a 'with' statement).
820 Variable* Scope::LookupRecursive(Handle<String> name, 820 Variable* Scope::LookupRecursive(Handle<String> name,
821 bool from_inner_function, 821 bool from_inner_scope,
822 Variable** invalidated_local) { 822 Variable** invalidated_local) {
823 // If we find a variable, but the current scope calls 'eval', the found 823 // If we find a variable, but the current scope calls 'eval', the found
824 // variable may not be the correct one (the 'eval' may introduce a 824 // variable may not be the correct one (the 'eval' may introduce a
825 // property with the same name). In that case, remember that the variable 825 // property with the same name). In that case, remember that the variable
826 // found is just a guess. 826 // found is just a guess.
827 bool guess = scope_calls_eval_; 827 bool guess = scope_calls_eval_;
828 828
829 // Try to find the variable in this scope. 829 // Try to find the variable in this scope.
830 Variable* var = LocalLookup(name); 830 Variable* var = LocalLookup(name);
831 831
832 if (var != NULL) { 832 if (var != NULL) {
833 // We found a variable. If this is not an inner lookup, we are done. 833 // We found a variable. If this is not an inner lookup, we are done.
834 // (Even if there is an 'eval' in this scope which introduces the 834 // (Even if there is an 'eval' in this scope which introduces the
835 // same variable again, the resulting variable remains the same. 835 // same variable again, the resulting variable remains the same.
836 // Note that enclosing 'with' statements are handled at the call site.) 836 // Note that enclosing 'with' statements are handled at the call site.)
837 if (!from_inner_function) 837 if (!from_inner_scope)
838 return var; 838 return var;
839 839
840 } else { 840 } else {
841 // We did not find a variable locally. Check against the function variable, 841 // We did not find a variable locally. Check against the function variable,
842 // if any. We can do this for all scopes, since the function variable is 842 // if any. We can do this for all scopes, since the function variable is
843 // only present - if at all - for function scopes. 843 // only present - if at all - for function scopes.
844 // 844 //
845 // This lookup corresponds to a lookup in the "intermediate" scope sitting 845 // This lookup corresponds to a lookup in the "intermediate" scope sitting
846 // between this scope and the outer scope. (ECMA-262, 3rd., requires that 846 // between this scope and the outer scope. (ECMA-262, 3rd., requires that
847 // the name of named function literal is kept in an intermediate scope 847 // the name of named function literal is kept in an intermediate scope
848 // in between this scope and the next outer scope.) 848 // in between this scope and the next outer scope.)
849 if (function_ != NULL && function_->name().is_identical_to(name)) { 849 if (function_ != NULL && function_->name().is_identical_to(name)) {
850 var = function_->var(); 850 var = function_->var();
851 851
852 } else if (outer_scope_ != NULL) { 852 } else if (outer_scope_ != NULL) {
853 var = outer_scope_->LookupRecursive( 853 var = outer_scope_->LookupRecursive(
Rico 2011/09/14 13:43:25 now fits on one line
854 name, 854 name,
855 is_function_scope() || from_inner_function, 855 true,
Steven 2011/09/14 13:30:17 The important change.
856 invalidated_local); 856 invalidated_local);
857 // We may have found a variable in an outer scope. However, if 857 // We may have found a variable in an outer scope. However, if
858 // the current scope is inside a 'with', the actual variable may 858 // the current scope is inside a 'with', the actual variable may
859 // be a property introduced via the 'with' statement. Then, the 859 // be a property introduced via the 'with' statement. Then, the
860 // variable we may have found is just a guess. 860 // variable we may have found is just a guess.
861 if (scope_inside_with_) 861 if (scope_inside_with_)
862 guess = true; 862 guess = true;
863 } 863 }
864 864
865 // If we did not find a variable, we are done. 865 // If we did not find a variable, we are done.
866 if (var == NULL) 866 if (var == NULL)
867 return NULL; 867 return NULL;
868 } 868 }
869 869
870 ASSERT(var != NULL); 870 ASSERT(var != NULL);
871 871
872 // If this is a lookup from an inner scope, mark the variable. 872 // If this is a lookup from an inner scope, mark the variable.
873 if (from_inner_function) { 873 if (from_inner_scope) {
874 var->MarkAsAccessedFromInnerFunctionScope(); 874 var->MarkAsAccessedFromInnerScope();
875 } 875 }
876 876
877 // If the variable we have found is just a guess, invalidate the 877 // If the variable we have found is just a guess, invalidate the
878 // result. If the found variable is local, record that fact so we 878 // result. If the found variable is local, record that fact so we
879 // can generate fast code to get it if it is not shadowed by eval. 879 // can generate fast code to get it if it is not shadowed by eval.
880 if (guess) { 880 if (guess) {
881 if (!var->is_global()) *invalidated_local = var; 881 if (!var->is_global()) *invalidated_local = var;
882 var = NULL; 882 var = NULL;
883 } 883 }
884 884
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 1015
1016 return scope_calls_eval_ || inner_scope_calls_eval_; 1016 return scope_calls_eval_ || inner_scope_calls_eval_;
1017 } 1017 }
1018 1018
1019 1019
1020 bool Scope::MustAllocate(Variable* var) { 1020 bool Scope::MustAllocate(Variable* var) {
1021 // Give var a read/write use if there is a chance it might be accessed 1021 // Give var a read/write use if there is a chance it might be accessed
1022 // via an eval() call. This is only possible if the variable has a 1022 // via an eval() call. This is only possible if the variable has a
1023 // visible name. 1023 // visible name.
1024 if ((var->is_this() || var->name()->length() > 0) && 1024 if ((var->is_this() || var->name()->length() > 0) &&
1025 (var->is_accessed_from_inner_function_scope() || 1025 (var->is_accessed_from_inner_scope() ||
1026 scope_calls_eval_ || 1026 scope_calls_eval_ ||
1027 inner_scope_calls_eval_ || 1027 inner_scope_calls_eval_ ||
1028 scope_contains_with_ || 1028 scope_contains_with_ ||
1029 is_catch_scope() || 1029 is_catch_scope() ||
1030 is_block_scope())) { 1030 is_block_scope())) {
1031 var->set_is_used(true); 1031 var->set_is_used(true);
1032 } 1032 }
1033 // Global variables do not need to be allocated. 1033 // Global variables do not need to be allocated.
1034 return !var->is_global() && var->is_used(); 1034 return !var->is_global() && var->is_used();
1035 } 1035 }
1036 1036
1037 1037
1038 bool Scope::MustAllocateInContext(Variable* var) { 1038 bool Scope::MustAllocateInContext(Variable* var) {
1039 // If var is accessed from an inner scope, or if there is a possibility 1039 // If var is accessed from an inner scope, or if there is a possibility
1040 // that it might be accessed from the current or an inner scope (through 1040 // that it might be accessed from the current or an inner scope (through
1041 // an eval() call or a runtime with lookup), it must be allocated in the 1041 // an eval() call or a runtime with lookup), it must be allocated in the
1042 // context. 1042 // context.
1043 // 1043 //
1044 // Exceptions: temporary variables are never allocated in a context; 1044 // Exceptions: temporary variables are never allocated in a context;
1045 // catch-bound variables are always allocated in a context. 1045 // catch-bound variables are always allocated in a context.
1046 if (var->mode() == Variable::TEMPORARY) return false; 1046 if (var->mode() == Variable::TEMPORARY) return false;
1047 if (is_catch_scope() || is_block_scope()) return true; 1047 if (is_catch_scope() || is_block_scope()) return true;
1048 return var->is_accessed_from_inner_function_scope() || 1048 return var->is_accessed_from_inner_scope() ||
1049 scope_calls_eval_ || 1049 scope_calls_eval_ ||
1050 inner_scope_calls_eval_ || 1050 inner_scope_calls_eval_ ||
1051 scope_contains_with_ || 1051 scope_contains_with_ ||
1052 var->is_global(); 1052 var->is_global();
1053 } 1053 }
1054 1054
1055 1055
1056 bool Scope::HasArgumentsParameter() { 1056 bool Scope::HasArgumentsParameter() {
1057 for (int i = 0; i < params_.length(); i++) { 1057 for (int i = 0; i < params_.length(); i++) {
1058 if (params_[i]->name().is_identical_to( 1058 if (params_[i]->name().is_identical_to(
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 // The same parameter may occur multiple times in the parameters_ list. 1104 // The same parameter may occur multiple times in the parameters_ list.
1105 // If it does, and if it is not copied into the context object, it must 1105 // If it does, and if it is not copied into the context object, it must
1106 // receive the highest parameter index for that parameter; thus iteration 1106 // receive the highest parameter index for that parameter; thus iteration
1107 // order is relevant! 1107 // order is relevant!
1108 for (int i = params_.length() - 1; i >= 0; --i) { 1108 for (int i = params_.length() - 1; i >= 0; --i) {
1109 Variable* var = params_[i]; 1109 Variable* var = params_[i];
1110 ASSERT(var->scope() == this); 1110 ASSERT(var->scope() == this);
1111 if (uses_nonstrict_arguments) { 1111 if (uses_nonstrict_arguments) {
1112 // Give the parameter a use from an inner scope, to force allocation 1112 // Give the parameter a use from an inner scope, to force allocation
1113 // to the context. 1113 // to the context.
1114 var->MarkAsAccessedFromInnerFunctionScope(); 1114 var->MarkAsAccessedFromInnerScope();
1115 } 1115 }
1116 1116
1117 if (MustAllocate(var)) { 1117 if (MustAllocate(var)) {
1118 if (MustAllocateInContext(var)) { 1118 if (MustAllocateInContext(var)) {
1119 ASSERT(var->IsUnallocated() || var->IsContextSlot()); 1119 ASSERT(var->IsUnallocated() || var->IsContextSlot());
1120 if (var->IsUnallocated()) { 1120 if (var->IsUnallocated()) {
1121 AllocateHeapSlot(var); 1121 AllocateHeapSlot(var);
1122 } 1122 }
1123 } else { 1123 } else {
1124 ASSERT(var->IsUnallocated() || var->IsParameter()); 1124 ASSERT(var->IsUnallocated() || var->IsParameter());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1202 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 1202 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1203 !must_have_local_context) { 1203 !must_have_local_context) {
1204 num_heap_slots_ = 0; 1204 num_heap_slots_ = 0;
1205 } 1205 }
1206 1206
1207 // Allocation done. 1207 // Allocation done.
1208 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1208 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1209 } 1209 }
1210 1210
1211 } } // namespace v8::internal 1211 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/variables.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698