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

Side by Side Diff: src/scopes.cc

Issue 968263002: [strong] Fix scoping related errors for methods. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: code review (arv@) Created 5 years, 9 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/scopes.h" 7 #include "src/scopes.h"
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 static const char* Header(ScopeType scope_type) { 791 static const char* Header(ScopeType scope_type) {
792 switch (scope_type) { 792 switch (scope_type) {
793 case EVAL_SCOPE: return "eval"; 793 case EVAL_SCOPE: return "eval";
794 case FUNCTION_SCOPE: return "function"; 794 case FUNCTION_SCOPE: return "function";
795 case MODULE_SCOPE: return "module"; 795 case MODULE_SCOPE: return "module";
796 case SCRIPT_SCOPE: return "global"; 796 case SCRIPT_SCOPE: return "global";
797 case CATCH_SCOPE: return "catch"; 797 case CATCH_SCOPE: return "catch";
798 case BLOCK_SCOPE: return "block"; 798 case BLOCK_SCOPE: return "block";
799 case WITH_SCOPE: return "with"; 799 case WITH_SCOPE: return "with";
800 case ARROW_SCOPE: return "arrow"; 800 case ARROW_SCOPE: return "arrow";
801 case CLASS_SCOPE:
802 return "class";
rossberg 2015/03/04 10:39:27 Nit: format like others.
marja 2015/03/04 11:14:38 clang-format wants it this way :/ Instead, formatt
rossberg 2015/03/04 12:39:33 I wish we would just fracking nuke this clang-form
801 } 803 }
802 UNREACHABLE(); 804 UNREACHABLE();
803 return NULL; 805 return NULL;
804 } 806 }
805 807
806 808
807 static void Indent(int n, const char* str) { 809 static void Indent(int n, const char* str) {
808 PrintF("%*s%s", n, "", str); 810 PrintF("%*s%s", n, "", str);
809 } 811 }
810 812
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 // (functions and consts may be resolved by the parser). 1065 // (functions and consts may be resolved by the parser).
1064 if (proxy->is_resolved()) return true; 1066 if (proxy->is_resolved()) return true;
1065 1067
1066 // Otherwise, try to resolve the variable. 1068 // Otherwise, try to resolve the variable.
1067 BindingKind binding_kind; 1069 BindingKind binding_kind;
1068 Variable* var = LookupRecursive(proxy, &binding_kind, factory); 1070 Variable* var = LookupRecursive(proxy, &binding_kind, factory);
1069 switch (binding_kind) { 1071 switch (binding_kind) {
1070 case BOUND: 1072 case BOUND:
1071 // We found a variable binding. 1073 // We found a variable binding.
1072 if (is_strong(language_mode())) { 1074 if (is_strong(language_mode())) {
1073 // Check for declaration-after use (for variables) in strong mode. Note 1075 if (!CheckStrongModeDeclaration(proxy, var)) return false;
1074 // that we can only do this in the case where we have seen the
1075 // declaration. And we always allow referencing functions (for now).
1076
1077 // If both the use and the declaration are inside an eval scope
1078 // (possibly indirectly), or one of them is, we need to check whether
1079 // they are inside the same eval scope or different
1080 // ones.
1081
1082 // TODO(marja,rossberg): Detect errors across different evals (depends
1083 // on the future of eval in strong mode).
1084 const Scope* eval_for_use = NearestOuterEvalScope();
1085 const Scope* eval_for_declaration =
1086 var->scope()->NearestOuterEvalScope();
1087
1088 if (proxy->position() != RelocInfo::kNoPosition &&
1089 proxy->position() < var->initializer_position() &&
1090 !var->is_function() && eval_for_use == eval_for_declaration) {
1091 DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
1092 ReportMessage(proxy->position(), proxy->end_position(),
1093 "strong_use_before_declaration", proxy->raw_name());
1094 return false;
1095 }
1096 } 1076 }
1097 break; 1077 break;
1098 1078
1099 case BOUND_EVAL_SHADOWED: 1079 case BOUND_EVAL_SHADOWED:
1100 // We either found a variable binding that might be shadowed by eval or 1080 // We either found a variable binding that might be shadowed by eval or
1101 // gave up on it (e.g. by encountering a local with the same in the outer 1081 // gave up on it (e.g. by encountering a local with the same in the outer
1102 // scope which was not promoted to a context, this can happen if we use 1082 // scope which was not promoted to a context, this can happen if we use
1103 // debugger to evaluate arbitrary expressions at a break point). 1083 // debugger to evaluate arbitrary expressions at a break point).
1104 if (var->IsGlobalObjectProperty()) { 1084 if (var->IsGlobalObjectProperty()) {
1105 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); 1085 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
(...skipping 24 matching lines...) Expand all
1130 1110
1131 DCHECK(var != NULL); 1111 DCHECK(var != NULL);
1132 if (proxy->is_assigned()) var->set_maybe_assigned(); 1112 if (proxy->is_assigned()) var->set_maybe_assigned();
1133 1113
1134 proxy->BindTo(var); 1114 proxy->BindTo(var);
1135 1115
1136 return true; 1116 return true;
1137 } 1117 }
1138 1118
1139 1119
1120 bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
1121 // Check for declaration-after use (for variables) in strong mode. Note that
1122 // we can only do this in the case where we have seen the declaration. And we
1123 // always allow referencing functions (for now).
1124
1125 // If both the use and the declaration are inside an eval scope (possibly
1126 // indirectly), or one of them is, we need to check whether they are inside
1127 // the same eval scope or different ones.
1128
1129 // TODO(marja,rossberg): Detect errors across different evals (depends on the
1130 // future of eval in strong mode).
1131 const Scope* eval_for_use = NearestOuterEvalScope();
1132 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope();
1133
1134 // Allow referencing the class name from methods, even though the initializer
1135 // position for class names is only after the body. Note that the only
1136 // variable declared in the class scope is the class name.
1137 bool legal_class_name_reference = false;
1138 if (var->scope()->is_class_scope()) {
1139 // Referencing the class name is only allowed inside methods of that class.
1140 Scope* scope = this;
1141 bool found_method_scope = false;
1142 while (scope && !found_method_scope && scope != var->scope()) {
1143 if (scope->is_function_scope() && scope->outer_scope_ == var->scope()) {
1144 found_method_scope = true;
rossberg 2015/03/04 10:39:27 Can't we simplify the logic by returning true here
marja 2015/03/04 11:14:38 Done.
1145 break;
1146 }
1147 scope = scope->outer_scope();
1148 }
1149 legal_class_name_reference = found_method_scope;
1150 }
1151
1152 if (proxy->position() != RelocInfo::kNoPosition &&
1153 proxy->position() < var->initializer_position() && !var->is_function() &&
1154 eval_for_use == eval_for_declaration && !legal_class_name_reference) {
1155 DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
1156 ReportMessage(proxy->position(), proxy->end_position(),
1157 "strong_use_before_declaration", proxy->raw_name());
1158 return false;
1159 }
1160 return true;
1161 }
1162
1163
1140 bool Scope::ResolveVariablesRecursively(CompilationInfo* info, 1164 bool Scope::ResolveVariablesRecursively(CompilationInfo* info,
1141 AstNodeFactory* factory) { 1165 AstNodeFactory* factory) {
1142 DCHECK(info->script_scope()->is_script_scope()); 1166 DCHECK(info->script_scope()->is_script_scope());
1143 1167
1144 // Resolve unresolved variables for this scope. 1168 // Resolve unresolved variables for this scope.
1145 for (int i = 0; i < unresolved_.length(); i++) { 1169 for (int i = 0; i < unresolved_.length(); i++) {
1146 if (!ResolveVariable(info, unresolved_[i], factory)) return false; 1170 if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1147 } 1171 }
1148 1172
1149 // Resolve unresolved variables for inner scopes. 1173 // Resolve unresolved variables for inner scopes.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 } 1218 }
1195 1219
1196 1220
1197 bool Scope::MustAllocate(Variable* var) { 1221 bool Scope::MustAllocate(Variable* var) {
1198 // Give var a read/write use if there is a chance it might be accessed 1222 // Give var a read/write use if there is a chance it might be accessed
1199 // via an eval() call. This is only possible if the variable has a 1223 // via an eval() call. This is only possible if the variable has a
1200 // visible name. 1224 // visible name.
1201 if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) && 1225 if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) &&
1202 (var->has_forced_context_allocation() || scope_calls_eval_ || 1226 (var->has_forced_context_allocation() || scope_calls_eval_ ||
1203 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || 1227 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
1204 is_block_scope() || is_module_scope() || is_script_scope())) { 1228 is_block_scope() || is_class_scope() || is_module_scope() ||
1229 is_script_scope())) {
1205 var->set_is_used(); 1230 var->set_is_used();
1206 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); 1231 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned();
1207 } 1232 }
1208 // Global variables do not need to be allocated. 1233 // Global variables do not need to be allocated.
1209 return !var->IsGlobalObjectProperty() && var->is_used(); 1234 return !var->IsGlobalObjectProperty() && var->is_used();
1210 } 1235 }
1211 1236
1212 1237
1213 bool Scope::MustAllocateInContext(Variable* var) { 1238 bool Scope::MustAllocateInContext(Variable* var) {
1214 // If var is accessed from an inner scope, or if there is a possibility 1239 // If var is accessed from an inner scope, or if there is a possibility
1215 // that it might be accessed from the current or an inner scope (through 1240 // that it might be accessed from the current or an inner scope (through
1216 // an eval() call or a runtime with lookup), it must be allocated in the 1241 // an eval() call or a runtime with lookup), it must be allocated in the
1217 // context. 1242 // context.
1218 // 1243 //
1219 // Exceptions: If the scope as a whole has forced context allocation, all 1244 // Exceptions: If the scope as a whole has forced context allocation, all
1220 // variables will have context allocation, even temporaries. Otherwise 1245 // variables will have context allocation, even temporaries. Otherwise
1221 // temporary variables are always stack-allocated. Catch-bound variables are 1246 // temporary variables are always stack-allocated. Catch-bound variables are
1222 // always context-allocated. 1247 // always context-allocated.
1223 if (has_forced_context_allocation()) return true; 1248 if (has_forced_context_allocation()) return true;
1224 if (var->mode() == TEMPORARY) return false; 1249 if (var->mode() == TEMPORARY) return false;
1225 if (var->mode() == INTERNAL) return true; 1250 if (var->mode() == INTERNAL) return true;
1226 if (is_catch_scope() || is_block_scope() || is_module_scope()) return true; 1251 if (is_catch_scope() || is_block_scope() || is_class_scope() ||
1252 is_module_scope()) {
1253 return true;
1254 }
1227 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; 1255 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true;
1228 return var->has_forced_context_allocation() || 1256 return var->has_forced_context_allocation() ||
1229 scope_calls_eval_ || 1257 scope_calls_eval_ ||
1230 inner_scope_calls_eval_ || 1258 inner_scope_calls_eval_ ||
1231 scope_contains_with_; 1259 scope_contains_with_;
1232 } 1260 }
1233 1261
1234 1262
1235 bool Scope::HasArgumentsParameter(Isolate* isolate) { 1263 bool Scope::HasArgumentsParameter(Isolate* isolate) {
1236 for (int i = 0; i < params_.length(); i++) { 1264 for (int i = 0; i < params_.length(); i++) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 } 1453 }
1426 1454
1427 1455
1428 int Scope::ContextLocalCount() const { 1456 int Scope::ContextLocalCount() const {
1429 if (num_heap_slots() == 0) return 0; 1457 if (num_heap_slots() == 0) return 0;
1430 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 1458 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1431 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); 1459 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1432 } 1460 }
1433 1461
1434 } } // namespace v8::internal 1462 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698