OLD | NEW |
---|---|
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 Loading... | |
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"; | |
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 Loading... | |
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 Loading... | |
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; | |
arv (Not doing code reviews)
2015/03/03 15:36:28
It is still not clear why this is only matching th
marja
2015/03/03 15:52:14
This check only fires when we have resolved the Va
| |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |