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

Side by Side Diff: src/scopes.cc

Issue 8431001: Tune context allocation for variables accessed from inner scopes. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month 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 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 } 700 }
701 701
702 702
703 static void PrintVar(int indent, Variable* var) { 703 static void PrintVar(int indent, Variable* var) {
704 if (var->is_used() || !var->IsUnallocated()) { 704 if (var->is_used() || !var->IsUnallocated()) {
705 Indent(indent, Variable::Mode2String(var->mode())); 705 Indent(indent, Variable::Mode2String(var->mode()));
706 PrintF(" "); 706 PrintF(" ");
707 PrintName(var->name()); 707 PrintName(var->name());
708 PrintF("; // "); 708 PrintF("; // ");
709 PrintLocation(var); 709 PrintLocation(var);
710 if (var->is_accessed_from_inner_scope()) { 710 if (var->has_forced_context_allocation()) {
711 if (!var->IsUnallocated()) PrintF(", "); 711 if (!var->IsUnallocated()) PrintF(", ");
712 PrintF("inner scope access"); 712 PrintF("forced context allocation");
713 } 713 }
714 PrintF("\n"); 714 PrintF("\n");
715 } 715 }
716 } 716 }
717 717
718 718
719 static void PrintMap(int indent, VariableMap* map) { 719 static void PrintMap(int indent, VariableMap* map) {
720 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { 720 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
721 Variable* var = reinterpret_cast<Variable*>(p->value); 721 Variable* var = reinterpret_cast<Variable*>(p->value);
722 PrintVar(indent, var); 722 PrintVar(indent, var);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 // This lookup corresponds to a lookup in the "intermediate" scope sitting 841 // This lookup corresponds to a lookup in the "intermediate" scope sitting
842 // between this scope and the outer scope. (ECMA-262, 3rd., requires that 842 // between this scope and the outer scope. (ECMA-262, 3rd., requires that
843 // the name of named function literal is kept in an intermediate scope 843 // the name of named function literal is kept in an intermediate scope
844 // in between this scope and the next outer scope.) 844 // in between this scope and the next outer scope.)
845 *binding_kind = UNBOUND; 845 *binding_kind = UNBOUND;
846 if (function_ != NULL && function_->name().is_identical_to(name)) { 846 if (function_ != NULL && function_->name().is_identical_to(name)) {
847 var = function_->var(); 847 var = function_->var();
848 *binding_kind = BOUND; 848 *binding_kind = BOUND;
849 } else if (outer_scope_ != NULL) { 849 } else if (outer_scope_ != NULL) {
850 var = outer_scope_->LookupRecursive(name, context, binding_kind); 850 var = outer_scope_->LookupRecursive(name, context, binding_kind);
851 if (*binding_kind == BOUND) var->MarkAsAccessedFromInnerScope(); 851 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
852 var->ForceContextAllocation();
853 }
852 } 854 }
853 855
854 if (is_with_scope()) { 856 if (is_with_scope()) {
855 // The current scope is a with scope, so the variable binding can not be 857 // The current scope is a with scope, so the variable binding can not be
856 // statically resolved. However, note that it was necessary to do a lookup 858 // statically resolved. However, note that it was necessary to do a lookup
857 // in the outer scope anyway, because if a binding exists in an outer scope, 859 // in the outer scope anyway, because if a binding exists in an outer scope,
858 // the associated variable has to be marked as potentially being accessed 860 // the associated variable has to be marked as potentially being accessed
859 // from inside of an inner with scope (the property may not be in the 'with' 861 // from inside of an inner with scope (the property may not be in the 'with'
860 // object). 862 // object).
861 *binding_kind = DYNAMIC_LOOKUP; 863 *binding_kind = DYNAMIC_LOOKUP;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 975
974 return scope_calls_eval_ || inner_scope_calls_eval_; 976 return scope_calls_eval_ || inner_scope_calls_eval_;
975 } 977 }
976 978
977 979
978 bool Scope::MustAllocate(Variable* var) { 980 bool Scope::MustAllocate(Variable* var) {
979 // Give var a read/write use if there is a chance it might be accessed 981 // Give var a read/write use if there is a chance it might be accessed
980 // via an eval() call. This is only possible if the variable has a 982 // via an eval() call. This is only possible if the variable has a
981 // visible name. 983 // visible name.
982 if ((var->is_this() || var->name()->length() > 0) && 984 if ((var->is_this() || var->name()->length() > 0) &&
983 (var->is_accessed_from_inner_scope() || 985 (var->has_forced_context_allocation() ||
984 scope_calls_eval_ || 986 scope_calls_eval_ ||
985 inner_scope_calls_eval_ || 987 inner_scope_calls_eval_ ||
986 scope_contains_with_ || 988 scope_contains_with_ ||
987 is_catch_scope() || 989 is_catch_scope() ||
988 is_block_scope())) { 990 is_block_scope())) {
989 var->set_is_used(true); 991 var->set_is_used(true);
990 } 992 }
991 // Global variables do not need to be allocated. 993 // Global variables do not need to be allocated.
992 return !var->is_global() && var->is_used(); 994 return !var->is_global() && var->is_used();
993 } 995 }
994 996
995 997
996 bool Scope::MustAllocateInContext(Variable* var) { 998 bool Scope::MustAllocateInContext(Variable* var) {
997 // If var is accessed from an inner scope, or if there is a possibility 999 // If var is accessed from an inner scope, or if there is a possibility
998 // that it might be accessed from the current or an inner scope (through 1000 // that it might be accessed from the current or an inner scope (through
999 // an eval() call or a runtime with lookup), it must be allocated in the 1001 // an eval() call or a runtime with lookup), it must be allocated in the
1000 // context. 1002 // context.
1001 // 1003 //
1002 // Exceptions: temporary variables are never allocated in a context; 1004 // Exceptions: temporary variables are never allocated in a context;
1003 // catch-bound variables are always allocated in a context. 1005 // catch-bound variables are always allocated in a context.
1004 if (var->mode() == TEMPORARY) return false; 1006 if (var->mode() == TEMPORARY) return false;
1005 if (is_catch_scope() || is_block_scope()) return true; 1007 if (is_catch_scope() || is_block_scope()) return true;
1006 return var->is_accessed_from_inner_scope() || 1008 return var->has_forced_context_allocation() ||
1007 scope_calls_eval_ || 1009 scope_calls_eval_ ||
1008 inner_scope_calls_eval_ || 1010 inner_scope_calls_eval_ ||
1009 scope_contains_with_ || 1011 scope_contains_with_ ||
1010 var->is_global(); 1012 var->is_global();
1011 } 1013 }
1012 1014
1013 1015
1014 bool Scope::HasArgumentsParameter() { 1016 bool Scope::HasArgumentsParameter() {
1015 for (int i = 0; i < params_.length(); i++) { 1017 for (int i = 0; i < params_.length(); i++) {
1016 if (params_[i]->name().is_identical_to( 1018 if (params_[i]->name().is_identical_to(
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 } 1062 }
1061 1063
1062 // The same parameter may occur multiple times in the parameters_ list. 1064 // The same parameter may occur multiple times in the parameters_ list.
1063 // If it does, and if it is not copied into the context object, it must 1065 // If it does, and if it is not copied into the context object, it must
1064 // receive the highest parameter index for that parameter; thus iteration 1066 // receive the highest parameter index for that parameter; thus iteration
1065 // order is relevant! 1067 // order is relevant!
1066 for (int i = params_.length() - 1; i >= 0; --i) { 1068 for (int i = params_.length() - 1; i >= 0; --i) {
1067 Variable* var = params_[i]; 1069 Variable* var = params_[i];
1068 ASSERT(var->scope() == this); 1070 ASSERT(var->scope() == this);
1069 if (uses_nonstrict_arguments) { 1071 if (uses_nonstrict_arguments) {
1070 // Give the parameter a use from an inner scope, to force allocation 1072 // Force context allocation of the parameter.
1071 // to the context. 1073 var->ForceContextAllocation();
1072 var->MarkAsAccessedFromInnerScope();
1073 } 1074 }
1074 1075
1075 if (MustAllocate(var)) { 1076 if (MustAllocate(var)) {
1076 if (MustAllocateInContext(var)) { 1077 if (MustAllocateInContext(var)) {
1077 ASSERT(var->IsUnallocated() || var->IsContextSlot()); 1078 ASSERT(var->IsUnallocated() || var->IsContextSlot());
1078 if (var->IsUnallocated()) { 1079 if (var->IsUnallocated()) {
1079 AllocateHeapSlot(var); 1080 AllocateHeapSlot(var);
1080 } 1081 }
1081 } else { 1082 } else {
1082 ASSERT(var->IsUnallocated() || var->IsParameter()); 1083 ASSERT(var->IsUnallocated() || var->IsParameter());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 1161 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1161 !must_have_local_context) { 1162 !must_have_local_context) {
1162 num_heap_slots_ = 0; 1163 num_heap_slots_ = 0;
1163 } 1164 }
1164 1165
1165 // Allocation done. 1166 // Allocation done.
1166 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1167 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1167 } 1168 }
1168 1169
1169 } } // namespace v8::internal 1170 } } // 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