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

Side by Side Diff: src/ast/scopes.cc

Issue 2262393004: Let LookupRecursive bind to NonLocals properly. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 4 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
« no previous file with comments | « src/ast/scopes.h ('k') | src/debug/debug-scopes.cc » ('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 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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | src/debug/debug-scopes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698