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/ast/scopes.h" | 5 #include "src/ast/scopes.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 // For scope analysis, debug-evaluate is equivalent to a with scope. | 265 // For scope analysis, debug-evaluate is equivalent to a with scope. |
266 Scope* with_scope = new (zone) | 266 Scope* with_scope = new (zone) |
267 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>()); | 267 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>()); |
268 // TODO(yangguo): Remove once debug-evaluate properly keeps track of the | 268 // TODO(yangguo): Remove once debug-evaluate properly keeps track of the |
269 // function scope in which we are evaluating. | 269 // function scope in which we are evaluating. |
270 if (context->IsDebugEvaluateContext()) { | 270 if (context->IsDebugEvaluateContext()) { |
271 with_scope->set_is_debug_evaluate_scope(); | 271 with_scope->set_is_debug_evaluate_scope(); |
272 } | 272 } |
273 current_scope = with_scope; | 273 current_scope = with_scope; |
274 } else if (context->IsScriptContext()) { | 274 } else if (context->IsScriptContext()) { |
| 275 // If we reach a script context, it's the outermost context with scope |
| 276 // info. The next context will be the native context. Install the scope |
| 277 // info of this script context onto the existing script scope to avoid |
| 278 // nesting script scopes. |
275 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 279 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
276 DCHECK_EQ(scope_info->scope_type(), SCRIPT_SCOPE); | 280 script_scope->SetScriptScopeInfo(scope_info); |
277 current_scope = new (zone) | 281 DCHECK(context->previous()->IsNativeContext()); |
278 DeclarationScope(zone, current_scope, SCRIPT_SCOPE, scope_info); | 282 break; |
279 } else if (context->IsFunctionContext()) { | 283 } else if (context->IsFunctionContext()) { |
280 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), | 284 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), |
281 isolate); | 285 isolate); |
282 // TODO(neis): For an eval scope, we currently create an ordinary function | 286 // TODO(neis): For an eval scope, we currently create an ordinary function |
283 // context. This is wrong and needs to be fixed. | 287 // context. This is wrong and needs to be fixed. |
284 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 | 288 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
285 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || | 289 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || |
286 scope_info->scope_type() == EVAL_SCOPE); | 290 scope_info->scope_type() == EVAL_SCOPE); |
287 DeclarationScope* function_scope = new (zone) | 291 DeclarationScope* function_scope = new (zone) |
288 DeclarationScope(zone, current_scope, FUNCTION_SCOPE, scope_info); | 292 DeclarationScope(zone, current_scope, FUNCTION_SCOPE, scope_info); |
(...skipping 17 matching lines...) Expand all Loading... |
306 new (zone) Scope(zone, current_scope, | 310 new (zone) Scope(zone, current_scope, |
307 ast_value_factory->GetString(handle(name, isolate))); | 311 ast_value_factory->GetString(handle(name, isolate))); |
308 } | 312 } |
309 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { | 313 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { |
310 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); | 314 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); |
311 } | 315 } |
312 if (innermost_scope == nullptr) innermost_scope = current_scope; | 316 if (innermost_scope == nullptr) innermost_scope = current_scope; |
313 context = context->previous(); | 317 context = context->previous(); |
314 } | 318 } |
315 | 319 |
| 320 if (innermost_scope == nullptr) return script_scope; |
316 script_scope->AddInnerScope(current_scope); | 321 script_scope->AddInnerScope(current_scope); |
317 script_scope->PropagateScopeInfo(); | 322 script_scope->PropagateScopeInfo(); |
318 return (innermost_scope == NULL) ? script_scope : innermost_scope; | 323 return innermost_scope; |
319 } | 324 } |
320 | 325 |
321 void Scope::DeserializeScopeInfo(Isolate* isolate, | 326 void Scope::DeserializeScopeInfo(Isolate* isolate, |
322 AstValueFactory* ast_value_factory) { | 327 AstValueFactory* ast_value_factory) { |
323 if (scope_info_.is_null()) return; | 328 if (scope_info_.is_null()) return; |
324 | 329 |
325 DCHECK(ThreadId::Current().Equals(isolate->thread_id())); | 330 DCHECK(ThreadId::Current().Equals(isolate->thread_id())); |
326 | 331 |
327 std::set<const AstRawString*> names_seen; | 332 std::set<const AstRawString*> names_seen; |
328 // Internalize context local & globals variables. | 333 // Internalize context local & globals variables. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 DeclarationScope* scope = info->literal()->scope(); | 420 DeclarationScope* scope = info->literal()->scope(); |
416 | 421 |
417 // We are compiling one of three cases: | 422 // We are compiling one of three cases: |
418 // 1) top-level code, | 423 // 1) top-level code, |
419 // 2) a function/eval/module on the top-level | 424 // 2) a function/eval/module on the top-level |
420 // 3) a function/eval in a scope that was already resolved. | 425 // 3) a function/eval in a scope that was already resolved. |
421 DCHECK(scope->scope_type() == SCRIPT_SCOPE || | 426 DCHECK(scope->scope_type() == SCRIPT_SCOPE || |
422 scope->outer_scope()->scope_type() == SCRIPT_SCOPE || | 427 scope->outer_scope()->scope_type() == SCRIPT_SCOPE || |
423 scope->outer_scope()->already_resolved_); | 428 scope->outer_scope()->already_resolved_); |
424 | 429 |
425 // Allocate the variables. | 430 scope->AllocateVariables(info); |
426 { | |
427 AstNodeFactory ast_node_factory(info->ast_value_factory()); | |
428 scope->AllocateVariables(info, &ast_node_factory); | |
429 } | |
430 | 431 |
431 #ifdef DEBUG | 432 #ifdef DEBUG |
432 if (info->script_is_native() ? FLAG_print_builtin_scopes | 433 if (info->script_is_native() ? FLAG_print_builtin_scopes |
433 : FLAG_print_scopes) { | 434 : FLAG_print_scopes) { |
434 scope->Print(); | 435 scope->Print(); |
435 } | 436 } |
436 scope->CheckScopePositions(); | 437 scope->CheckScopePositions(); |
437 scope->CheckZones(); | 438 scope->CheckZones(); |
438 #endif | 439 #endif |
439 } | 440 } |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 if (var->IsStackLocal()) { | 838 if (var->IsStackLocal()) { |
838 stack_locals->Add(var, zone()); | 839 stack_locals->Add(var, zone()); |
839 } else if (var->IsContextSlot()) { | 840 } else if (var->IsContextSlot()) { |
840 context_locals->Add(var, zone()); | 841 context_locals->Add(var, zone()); |
841 } else if (var->IsGlobalSlot()) { | 842 } else if (var->IsGlobalSlot()) { |
842 context_globals->Add(var, zone()); | 843 context_globals->Add(var, zone()); |
843 } | 844 } |
844 } | 845 } |
845 } | 846 } |
846 | 847 |
847 void DeclarationScope::AllocateVariables(ParseInfo* info, | 848 void DeclarationScope::AllocateVariables(ParseInfo* info) { |
848 AstNodeFactory* factory) { | |
849 // 1) Propagate scope information. | 849 // 1) Propagate scope information. |
850 PropagateScopeInfo(); | 850 PropagateScopeInfo(); |
851 | 851 |
852 // 2) Resolve variables. | 852 // 2) Resolve variables. |
853 ResolveVariablesRecursively(info, factory); | 853 ResolveVariablesRecursively(info); |
854 | 854 |
855 // 3) Allocate variables. | 855 // 3) Allocate variables. |
856 AllocateVariablesRecursively(); | 856 AllocateVariablesRecursively(); |
857 } | 857 } |
858 | 858 |
859 | 859 |
860 bool Scope::AllowsLazyParsing() const { | 860 bool Scope::AllowsLazyParsing() const { |
861 // If we are inside a block scope, we must parse eagerly to find out how | 861 // If we are inside a block scope, we must parse eagerly to find out how |
862 // to allocate variables on the block scope. At this point, declarations may | 862 // to allocate variables on the block scope. At this point, declarations may |
863 // not have yet been parsed. | 863 // not have yet been parsed. |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 // Declare a new non-local. | 1222 // Declare a new non-local. |
1223 DCHECK(!IsLexicalVariableMode(mode)); | 1223 DCHECK(!IsLexicalVariableMode(mode)); |
1224 var = map->Declare(zone(), NULL, name, mode, Variable::NORMAL, | 1224 var = map->Declare(zone(), NULL, name, mode, Variable::NORMAL, |
1225 kCreatedInitialized); | 1225 kCreatedInitialized); |
1226 // Allocate it by giving it a dynamic lookup. | 1226 // Allocate it by giving it a dynamic lookup. |
1227 var->AllocateTo(VariableLocation::LOOKUP, -1); | 1227 var->AllocateTo(VariableLocation::LOOKUP, -1); |
1228 } | 1228 } |
1229 return var; | 1229 return var; |
1230 } | 1230 } |
1231 | 1231 |
1232 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 1232 Variable* Scope::LookupRecursive(VariableProxy* proxy, bool declare_free, |
1233 BindingKind* binding_kind, | |
1234 AstNodeFactory* factory, | |
1235 Scope* outer_scope_end) { | 1233 Scope* outer_scope_end) { |
1236 DCHECK_NE(outer_scope_end, this); | 1234 DCHECK_NE(outer_scope_end, this); |
1237 DCHECK_NOT_NULL(binding_kind); | |
1238 DCHECK_EQ(UNBOUND, *binding_kind); | |
1239 // Short-cut: whenever we find a debug-evaluate scope, just look everything up | 1235 // Short-cut: whenever we find a debug-evaluate scope, just look everything up |
1240 // dynamically. Debug-evaluate doesn't properly create scope info for the | 1236 // dynamically. Debug-evaluate doesn't properly create scope info for the |
1241 // lookups it does. It may not have a valid 'this' declaration, and anything | 1237 // lookups it does. It may not have a valid 'this' declaration, and anything |
1242 // accessed through debug-evaluate might invalidly resolve to stack-allocated | 1238 // accessed through debug-evaluate might invalidly resolve to stack-allocated |
1243 // variables. | 1239 // variables. |
1244 // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for the | 1240 // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for the |
1245 // scopes in which it's evaluating. | 1241 // scopes in which it's evaluating. |
1246 if (is_debug_evaluate_scope_) { | 1242 if (is_debug_evaluate_scope_) { |
1247 *binding_kind = DYNAMIC_LOOKUP; | 1243 if (!declare_free) return nullptr; |
1248 return nullptr; | 1244 return NonLocal(proxy->raw_name(), DYNAMIC); |
1249 } | 1245 } |
1250 | 1246 |
1251 // Try to find the variable in this scope. | 1247 // Try to find the variable in this scope. |
1252 Variable* var = LookupLocal(proxy->raw_name()); | 1248 Variable* var = LookupLocal(proxy->raw_name()); |
1253 | 1249 |
1254 // We found a variable and we are done. (Even if there is an 'eval' in this | 1250 // We found a variable and we are done. (Even if there is an 'eval' in this |
1255 // scope which introduces the same variable again, the resulting variable | 1251 // scope which introduces the same variable again, the resulting variable |
1256 // remains the same.) | 1252 // remains the same.) |
1257 if (var != nullptr) { | 1253 if (var != nullptr) return var; |
1258 *binding_kind = BOUND; | |
1259 return var; | |
1260 } | |
1261 | 1254 |
1262 // We did not find a variable locally. Check against the function variable, if | 1255 // We did not find a variable locally. Check against the function variable, if |
1263 // any. | 1256 // any. |
1264 if (is_function_scope()) { | 1257 if (is_function_scope()) { |
1265 var = AsDeclarationScope()->LookupFunctionVar(proxy->raw_name()); | 1258 var = AsDeclarationScope()->LookupFunctionVar(proxy->raw_name()); |
1266 if (var != nullptr) { | 1259 if (var != nullptr) { |
1267 *binding_kind = calls_sloppy_eval() ? BOUND_EVAL_SHADOWED : BOUND; | 1260 if (calls_sloppy_eval()) return NonLocal(proxy->raw_name(), DYNAMIC); |
1268 return var; | 1261 return var; |
1269 } | 1262 } |
1270 } | 1263 } |
1271 | 1264 |
1272 if (outer_scope_ != outer_scope_end) { | 1265 if (outer_scope_ == outer_scope_end) { |
1273 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory, | 1266 if (!declare_free) return nullptr; |
1274 outer_scope_end); | 1267 DCHECK(is_script_scope()); |
1275 if (*binding_kind == BOUND && is_function_scope()) { | 1268 // No binding has been found. Declare a variable on the global object. |
1276 var->ForceContextAllocation(); | 1269 return AsDeclarationScope()->DeclareDynamicGlobal(proxy->raw_name(), |
1277 } | 1270 Variable::NORMAL); |
1278 // "this" can't be shadowed by "eval"-introduced bindings or by "with" | |
1279 // scopes. | |
1280 // TODO(wingo): There are other variables in this category; add them. | |
1281 if (var != nullptr && var->is_this()) return var; | |
1282 | |
1283 if (is_with_scope()) { | |
1284 // The current scope is a with scope, so the variable binding can not be | |
1285 // statically resolved. However, note that it was necessary to do a lookup | |
1286 // in the outer scope anyway, because if a binding exists in an outer | |
1287 // scope, the associated variable has to be marked as potentially being | |
1288 // accessed from inside of an inner with scope (the property may not be in | |
1289 // the 'with' object). | |
1290 if (var != nullptr && var->IsUnallocated()) { | |
1291 DCHECK(!already_resolved_); | |
1292 var->set_is_used(); | |
1293 var->ForceContextAllocation(); | |
1294 if (proxy->is_assigned()) var->set_maybe_assigned(); | |
1295 } | |
1296 *binding_kind = DYNAMIC_LOOKUP; | |
1297 return nullptr; | |
1298 } | |
1299 } else { | |
1300 DCHECK(!is_with_scope()); | |
1301 DCHECK(is_function_scope() || is_script_scope() || is_eval_scope()); | |
1302 } | 1271 } |
1303 | 1272 |
1304 if (calls_sloppy_eval() && is_declaration_scope() && !is_script_scope()) { | 1273 DCHECK(!is_script_scope()); |
| 1274 |
| 1275 var = outer_scope_->LookupRecursive(proxy, declare_free, outer_scope_end); |
| 1276 |
| 1277 // The variable could not be resolved statically. |
| 1278 if (var == nullptr) return var; |
| 1279 |
| 1280 if (is_function_scope() && !var->is_dynamic()) { |
| 1281 var->ForceContextAllocation(); |
| 1282 } |
| 1283 // "this" can't be shadowed by "eval"-introduced bindings or by "with" |
| 1284 // scopes. |
| 1285 // TODO(wingo): There are other variables in this category; add them. |
| 1286 if (var->is_this()) return var; |
| 1287 |
| 1288 if (is_with_scope()) { |
| 1289 // The current scope is a with scope, so the variable binding can not be |
| 1290 // statically resolved. However, note that it was necessary to do a lookup |
| 1291 // in the outer scope anyway, because if a binding exists in an outer |
| 1292 // scope, the associated variable has to be marked as potentially being |
| 1293 // accessed from inside of an inner with scope (the property may not be in |
| 1294 // the 'with' object). |
| 1295 if (!var->is_dynamic() && var->IsUnallocated()) { |
| 1296 DCHECK(!already_resolved_); |
| 1297 var->set_is_used(); |
| 1298 var->ForceContextAllocation(); |
| 1299 if (proxy->is_assigned()) var->set_maybe_assigned(); |
| 1300 } |
| 1301 return NonLocal(proxy->raw_name(), DYNAMIC); |
| 1302 } |
| 1303 |
| 1304 if (calls_sloppy_eval() && is_declaration_scope()) { |
1305 // A variable binding may have been found in an outer scope, but the current | 1305 // A variable binding may have been found in an outer scope, but the current |
1306 // scope makes a sloppy 'eval' call, so the found variable may not be the | 1306 // scope makes a sloppy 'eval' call, so the found variable may not be the |
1307 // correct one (the 'eval' may introduce a binding with the same name). In | 1307 // correct one (the 'eval' may introduce a binding with the same name). In |
1308 // that case, change the lookup result to reflect this situation. Only | 1308 // that case, change the lookup result to reflect this situation. Only |
1309 // scopes that can host var bindings (declaration scopes) need be considered | 1309 // scopes that can host var bindings (declaration scopes) need be considered |
1310 // here (this excludes block and catch scopes), and variable lookups at | 1310 // here (this excludes block and catch scopes), and variable lookups at |
1311 // script scope are always dynamic. | 1311 // script scope are always dynamic. |
1312 if (*binding_kind == BOUND) { | 1312 if (var->IsGlobalObjectProperty()) { |
1313 *binding_kind = BOUND_EVAL_SHADOWED; | 1313 return NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
1314 } else if (*binding_kind == UNBOUND) { | |
1315 *binding_kind = UNBOUND_EVAL_SHADOWED; | |
1316 } | 1314 } |
| 1315 |
| 1316 if (var->is_dynamic()) return var; |
| 1317 |
| 1318 Variable* invalidated = var; |
| 1319 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL); |
| 1320 var->set_local_if_not_shadowed(invalidated); |
1317 } | 1321 } |
1318 | 1322 |
1319 return var; | 1323 return var; |
1320 } | 1324 } |
1321 | 1325 |
1322 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, | 1326 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) { |
1323 AstNodeFactory* factory) { | |
1324 DCHECK(info->script_scope()->is_script_scope()); | 1327 DCHECK(info->script_scope()->is_script_scope()); |
1325 | 1328 |
1326 // If the proxy is already resolved there's nothing to do | 1329 // If the proxy is already resolved there's nothing to do |
1327 // (functions and consts may be resolved by the parser). | 1330 // (functions and consts may be resolved by the parser). |
1328 if (proxy->is_resolved()) return; | 1331 if (proxy->is_resolved()) return; |
1329 | 1332 |
1330 // Otherwise, try to resolve the variable. | 1333 // Otherwise, try to resolve the variable. |
1331 BindingKind binding_kind = UNBOUND; | 1334 Variable* var = LookupRecursive(proxy, true, nullptr); |
1332 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | |
1333 | 1335 |
1334 ResolveTo(info, binding_kind, proxy, var); | 1336 ResolveTo(info, proxy, var); |
1335 } | 1337 } |
1336 | 1338 |
1337 void Scope::ResolveTo(ParseInfo* info, BindingKind binding_kind, | 1339 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) { |
1338 VariableProxy* proxy, Variable* var) { | |
1339 #ifdef DEBUG | 1340 #ifdef DEBUG |
1340 if (info->script_is_native()) { | 1341 if (info->script_is_native()) { |
1341 // To avoid polluting the global object in native scripts | 1342 // To avoid polluting the global object in native scripts |
1342 // - Variables must not be allocated to the global scope. | 1343 // - Variables must not be allocated to the global scope. |
1343 CHECK_NOT_NULL(outer_scope()); | 1344 CHECK_NOT_NULL(outer_scope()); |
1344 // - Variables must be bound locally or unallocated. | 1345 // - Variables must be bound locally or unallocated. |
1345 if (BOUND != binding_kind) { | 1346 if (var->IsGlobalObjectProperty()) { |
1346 // The following variable name may be minified. If so, disable | 1347 // The following variable name may be minified. If so, disable |
1347 // minification in js2c.py for better output. | 1348 // minification in js2c.py for better output. |
1348 Handle<String> name = proxy->raw_name()->string(); | 1349 Handle<String> name = proxy->raw_name()->string(); |
1349 V8_Fatal(__FILE__, __LINE__, "Unbound variable: '%s' in native script.", | 1350 V8_Fatal(__FILE__, __LINE__, "Unbound variable: '%s' in native script.", |
1350 name->ToCString().get()); | 1351 name->ToCString().get()); |
1351 } | 1352 } |
1352 VariableLocation location = var->location(); | 1353 VariableLocation location = var->location(); |
1353 CHECK(location == VariableLocation::LOCAL || | 1354 CHECK(location == VariableLocation::LOCAL || |
1354 location == VariableLocation::CONTEXT || | 1355 location == VariableLocation::CONTEXT || |
1355 location == VariableLocation::PARAMETER || | 1356 location == VariableLocation::PARAMETER || |
1356 location == VariableLocation::UNALLOCATED); | 1357 location == VariableLocation::UNALLOCATED); |
1357 } | 1358 } |
1358 #endif | 1359 #endif |
1359 | 1360 |
1360 switch (binding_kind) { | 1361 DCHECK_NOT_NULL(var); |
1361 case BOUND: | |
1362 break; | |
1363 | |
1364 case BOUND_EVAL_SHADOWED: | |
1365 // We either found a variable binding that might be shadowed by eval or | |
1366 // gave up on it (e.g. by encountering a local with the same in the outer | |
1367 // scope which was not promoted to a context, this can happen if we use | |
1368 // debugger to evaluate arbitrary expressions at a break point). | |
1369 if (var->IsGlobalObjectProperty()) { | |
1370 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | |
1371 } else if (var->is_dynamic()) { | |
1372 var = NonLocal(proxy->raw_name(), DYNAMIC); | |
1373 } else { | |
1374 Variable* invalidated = var; | |
1375 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL); | |
1376 var->set_local_if_not_shadowed(invalidated); | |
1377 } | |
1378 break; | |
1379 | |
1380 case UNBOUND: | |
1381 // No binding has been found. Declare a variable on the global object. | |
1382 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name(), | |
1383 Variable::NORMAL); | |
1384 break; | |
1385 | |
1386 case UNBOUND_EVAL_SHADOWED: | |
1387 // No binding has been found. But some scope makes a sloppy 'eval' call. | |
1388 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | |
1389 break; | |
1390 | |
1391 case DYNAMIC_LOOKUP: | |
1392 // The variable could not be resolved statically. | |
1393 var = NonLocal(proxy->raw_name(), DYNAMIC); | |
1394 break; | |
1395 } | |
1396 | |
1397 DCHECK(var != NULL); | |
1398 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1362 if (proxy->is_assigned()) var->set_maybe_assigned(); |
1399 | |
1400 proxy->BindTo(var); | 1363 proxy->BindTo(var); |
1401 } | 1364 } |
1402 | 1365 |
1403 void Scope::ResolveVariablesRecursively(ParseInfo* info, | 1366 void Scope::ResolveVariablesRecursively(ParseInfo* info) { |
1404 AstNodeFactory* factory) { | |
1405 DCHECK(info->script_scope()->is_script_scope()); | 1367 DCHECK(info->script_scope()->is_script_scope()); |
1406 | 1368 |
1407 // Resolve unresolved variables for this scope. | 1369 // Resolve unresolved variables for this scope. |
1408 for (VariableProxy* proxy = unresolved_; proxy != nullptr; | 1370 for (VariableProxy* proxy = unresolved_; proxy != nullptr; |
1409 proxy = proxy->next_unresolved()) { | 1371 proxy = proxy->next_unresolved()) { |
1410 ResolveVariable(info, proxy, factory); | 1372 ResolveVariable(info, proxy); |
1411 } | 1373 } |
1412 | 1374 |
1413 // Resolve unresolved variables for inner scopes. | 1375 // Resolve unresolved variables for inner scopes. |
1414 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1376 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1415 scope->ResolveVariablesRecursively(info, factory); | 1377 scope->ResolveVariablesRecursively(info); |
1416 } | 1378 } |
1417 } | 1379 } |
1418 | 1380 |
1419 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, | 1381 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
1420 ParseInfo* info, | 1382 ParseInfo* info, |
1421 VariableProxy* stack) { | 1383 VariableProxy* stack) { |
1422 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; | 1384 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; |
1423 proxy = next) { | 1385 proxy = next) { |
1424 next = proxy->next_unresolved(); | 1386 next = proxy->next_unresolved(); |
1425 if (proxy->is_resolved()) continue; | 1387 if (proxy->is_resolved()) continue; |
1426 // Note that we pass nullptr as AstNodeFactory: this phase should not create | 1388 Variable* var = |
1427 // any new AstNodes, since none of the Scopes involved are backed up by | 1389 LookupRecursive(proxy, false, max_outer_scope->outer_scope()); |
1428 // ScopeInfo. | |
1429 BindingKind binding_kind = UNBOUND; | |
1430 Variable* var = LookupRecursive(proxy, &binding_kind, nullptr, | |
1431 max_outer_scope->outer_scope()); | |
1432 if (var == nullptr) { | 1390 if (var == nullptr) { |
1433 proxy->set_next_unresolved(stack); | 1391 proxy->set_next_unresolved(stack); |
1434 stack = proxy; | 1392 stack = proxy; |
1435 } else if (info != nullptr) { | 1393 } else if (info != nullptr) { |
1436 DCHECK_NE(UNBOUND, binding_kind); | 1394 ResolveTo(info, proxy, var); |
1437 DCHECK_NE(UNBOUND_EVAL_SHADOWED, binding_kind); | |
1438 ResolveTo(info, binding_kind, proxy, var); | |
1439 } | 1395 } |
1440 } | 1396 } |
1441 | 1397 |
1442 // Clear unresolved_ as it's in an inconsistent state. | 1398 // Clear unresolved_ as it's in an inconsistent state. |
1443 unresolved_ = nullptr; | 1399 unresolved_ = nullptr; |
1444 | 1400 |
1445 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1401 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1446 stack = scope->FetchFreeVariables(max_outer_scope, info, stack); | 1402 stack = scope->FetchFreeVariables(max_outer_scope, info, stack); |
1447 } | 1403 } |
1448 | 1404 |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1725 function != nullptr && function->IsContextSlot(); | 1681 function != nullptr && function->IsContextSlot(); |
1726 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1682 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1727 (is_function_var_in_context ? 1 : 0); | 1683 (is_function_var_in_context ? 1 : 0); |
1728 } | 1684 } |
1729 | 1685 |
1730 | 1686 |
1731 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1687 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1732 | 1688 |
1733 } // namespace internal | 1689 } // namespace internal |
1734 } // namespace v8 | 1690 } // namespace v8 |
OLD | NEW |