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

Side by Side Diff: src/parser.cc

Issue 8508052: Static resolution of outer variables in eval code. (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 | « src/contexts.cc ('k') | src/runtime.cc » ('j') | src/runtime.cc » ('J')
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 717 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 728
729 mode_ = PARSE_EAGERLY; 729 mode_ = PARSE_EAGERLY;
730 730
731 // Place holder for the result. 731 // Place holder for the result.
732 FunctionLiteral* result = NULL; 732 FunctionLiteral* result = NULL;
733 733
734 { 734 {
735 // Parse the function literal. 735 // Parse the function literal.
736 Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); 736 Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
737 if (!info->closure().is_null()) { 737 if (!info->closure().is_null()) {
738 scope = Scope::DeserializeScopeChain(info, scope); 738 scope = Scope::DeserializeScopeChain(info->closure()->context(), scope);
739 } 739 }
740 FunctionState function_state(this, scope, isolate()); 740 FunctionState function_state(this, scope, isolate());
741 ASSERT(scope->strict_mode_flag() == kNonStrictMode || 741 ASSERT(scope->strict_mode_flag() == kNonStrictMode ||
742 scope->strict_mode_flag() == info->strict_mode_flag()); 742 scope->strict_mode_flag() == info->strict_mode_flag());
743 ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag()); 743 ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag());
744 scope->SetStrictModeFlag(shared_info->strict_mode_flag()); 744 scope->SetStrictModeFlag(shared_info->strict_mode_flag());
745 FunctionLiteral::Type type = shared_info->is_expression() 745 FunctionLiteral::Type type = shared_info->is_expression()
746 ? (shared_info->is_anonymous() 746 ? (shared_info->is_anonymous()
747 ? FunctionLiteral::ANONYMOUS_EXPRESSION 747 ? FunctionLiteral::ANONYMOUS_EXPRESSION
748 : FunctionLiteral::NAMED_EXPRESSION) 748 : FunctionLiteral::NAMED_EXPRESSION)
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 bool resolve, 1355 bool resolve,
1356 bool* ok) { 1356 bool* ok) {
1357 Variable* var = NULL; 1357 Variable* var = NULL;
1358 // If we are inside a function, a declaration of a var/const variable is a 1358 // If we are inside a function, a declaration of a var/const variable is a
1359 // truly local variable, and the scope of the variable is always the function 1359 // truly local variable, and the scope of the variable is always the function
1360 // scope. 1360 // scope.
1361 // Let/const variables in harmony mode are always added to the immediately 1361 // Let/const variables in harmony mode are always added to the immediately
1362 // enclosing scope. 1362 // enclosing scope.
1363 Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY) 1363 Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
1364 ? top_scope_ : top_scope_->DeclarationScope(); 1364 ? top_scope_ : top_scope_->DeclarationScope();
1365 InitializationFlag init_flag = (fun != NULL || mode == VAR)
1366 ? kCreatedInitialized : kNeedsInitialization;
1365 1367
1366 // If a function scope exists, then we can statically declare this 1368 // If a function scope exists, then we can statically declare this
1367 // variable and also set its mode. In any case, a Declaration node 1369 // variable and also set its mode. In any case, a Declaration node
1368 // will be added to the scope so that the declaration can be added 1370 // will be added to the scope so that the declaration can be added
1369 // to the corresponding activation frame at runtime if necessary. 1371 // to the corresponding activation frame at runtime if necessary.
1370 // For instance declarations inside an eval scope need to be added 1372 // For instance declarations inside an eval scope need to be added
1371 // to the calling function context. 1373 // to the calling function context.
1372 // Similarly, strict mode eval scope does not leak variable declarations to 1374 // Similarly, strict mode eval scope does not leak variable declarations to
1373 // the caller's scope so we declare all locals, too. 1375 // the caller's scope so we declare all locals, too.
1374 // Also for block scoped let/const bindings the variable can be 1376 // Also for block scoped let/const bindings the variable can be
1375 // statically declared. 1377 // statically declared.
1376 if (declaration_scope->is_function_scope() || 1378 if (declaration_scope->is_function_scope() ||
1377 declaration_scope->is_strict_mode_eval_scope() || 1379 declaration_scope->is_strict_mode_eval_scope() ||
1378 declaration_scope->is_block_scope()) { 1380 declaration_scope->is_block_scope()) {
1379 // Declare the variable in the function scope. 1381 // Declare the variable in the function scope.
1380 var = declaration_scope->LocalLookup(name); 1382 var = declaration_scope->LocalLookup(name);
1381 if (var == NULL) { 1383 if (var == NULL) {
1382 // Declare the name. 1384 // Declare the name.
1383 InitializationFlag init_flag = (fun != NULL || mode == VAR)
1384 ? kCreatedInitialized : kNeedsInitialization;
1385 var = declaration_scope->DeclareLocal(name, mode, init_flag); 1385 var = declaration_scope->DeclareLocal(name, mode, init_flag);
1386 } else { 1386 } else {
1387 // The name was declared in this scope before; check for conflicting 1387 // The name was declared in this scope before; check for conflicting
1388 // re-declarations. We have a conflict if either of the declarations is 1388 // re-declarations. We have a conflict if either of the declarations is
1389 // not a var. There is similar code in runtime.cc in the Declare 1389 // not a var. There is similar code in runtime.cc in the Declare
1390 // functions. The function CheckNonConflictingScope checks for conflicting 1390 // functions. The function CheckNonConflictingScope checks for conflicting
1391 // var and let bindings from different scopes whereas this is a check for 1391 // var and let bindings from different scopes whereas this is a check for
1392 // conflicting declarations within the same scope. This check also covers 1392 // conflicting declarations within the same scope. This check also covers
1393 // 1393 //
1394 // function () { let x; { var x; } } 1394 // function () { let x; { var x; } }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 // WARNING: This will lead to multiple declaration nodes for the 1437 // WARNING: This will lead to multiple declaration nodes for the
1438 // same variable if it is declared several times. This is not a 1438 // same variable if it is declared several times. This is not a
1439 // semantic issue as long as we keep the source order, but it may be 1439 // semantic issue as long as we keep the source order, but it may be
1440 // a performance issue since it may lead to repeated 1440 // a performance issue since it may lead to repeated
1441 // Runtime::DeclareContextSlot() calls. 1441 // Runtime::DeclareContextSlot() calls.
1442 VariableProxy* proxy = declaration_scope->NewUnresolved( 1442 VariableProxy* proxy = declaration_scope->NewUnresolved(
1443 name, scanner().location().beg_pos); 1443 name, scanner().location().beg_pos);
1444 declaration_scope->AddDeclaration( 1444 declaration_scope->AddDeclaration(
1445 new(zone()) Declaration(proxy, mode, fun, top_scope_)); 1445 new(zone()) Declaration(proxy, mode, fun, top_scope_));
1446 1446
1447 // For global const variables we bind the proxy to a variable.
1448 if ((mode == CONST || mode == CONST_HARMONY) && 1447 if ((mode == CONST || mode == CONST_HARMONY) &&
1449 declaration_scope->is_global_scope()) { 1448 declaration_scope->is_global_scope()) {
1449 // For global const variables we bind the proxy to a variable.
1450 ASSERT(resolve); // should be set by all callers 1450 ASSERT(resolve); // should be set by all callers
1451 Variable::Kind kind = Variable::NORMAL; 1451 Variable::Kind kind = Variable::NORMAL;
1452 var = new(zone()) Variable(declaration_scope, 1452 var = new(zone()) Variable(declaration_scope,
1453 name, 1453 name,
1454 CONST, 1454 mode,
1455 true, 1455 true,
1456 kind, 1456 kind,
1457 kNeedsInitialization); 1457 kNeedsInitialization);
1458 } else if (declaration_scope->is_eval_scope() &&
1459 !declaration_scope->is_strict_mode()) {
1460 // For variable declarations in a non-strict eval scope the proxy is bound
1461 // to a lookup variable to force a dynamic declaration using the
1462 // DeclareContextSlot runtime function.
1463 Variable::Kind kind = Variable::NORMAL;
1464 var = new(zone()) Variable(declaration_scope,
1465 name,
1466 mode,
1467 true,
1468 kind,
1469 init_flag);
1470 var->AllocateTo(Variable::LOOKUP, -1);
1471 resolve = true;
1458 } 1472 }
1459 1473
1460 // If requested and we have a local variable, bind the proxy to the variable 1474 // If requested and we have a local variable, bind the proxy to the variable
1461 // at parse-time. This is used for functions (and consts) declared inside 1475 // at parse-time. This is used for functions (and consts) declared inside
1462 // statements: the corresponding function (or const) variable must be in the 1476 // statements: the corresponding function (or const) variable must be in the
1463 // function scope and not a statement-local scope, e.g. as provided with a 1477 // function scope and not a statement-local scope, e.g. as provided with a
1464 // 'with' statement: 1478 // 'with' statement:
1465 // 1479 //
1466 // with (obj) { 1480 // with (obj) {
1467 // function f() {} 1481 // function f() {}
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 // the number of arguments (2 or 3). 1908 // the number of arguments (2 or 3).
1895 initialize = 1909 initialize =
1896 new(zone()) CallRuntime( 1910 new(zone()) CallRuntime(
1897 isolate(), 1911 isolate(),
1898 isolate()->factory()->InitializeVarGlobal_symbol(), 1912 isolate()->factory()->InitializeVarGlobal_symbol(),
1899 Runtime::FunctionForId(Runtime::kInitializeVarGlobal), 1913 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1900 arguments); 1914 arguments);
1901 } 1915 }
1902 1916
1903 block->AddStatement(new(zone()) ExpressionStatement(initialize)); 1917 block->AddStatement(new(zone()) ExpressionStatement(initialize));
1918 } else if (needs_init) {
1919 // Constant initializations always assign to the declared constant which
1920 // is always at the function scope level. This is only relevant for
1921 // dynamically looked-up variables and constants (the start context for
1922 // constant lookups is always the function context, while it is the top
1923 // context for var declared variables). Sigh...
1924 // For 'let' and 'const' declared variables in harmony mode the
1925 // initialization also always assigns to the declared variable.
1926 ASSERT(proxy != NULL);
1927 ASSERT(proxy->var() != NULL);
1928 ASSERT(value != NULL);
1929 Assignment* assignment =
1930 new(zone()) Assignment(isolate(), init_op, proxy, value, position);
1931 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1932 value = NULL;
1904 } 1933 }
1905 1934
1906 // Add an assignment node to the initialization statement block if we still 1935 // Add an assignment node to the initialization statement block if we still
1907 // have a pending initialization value. We must distinguish between 1936 // have a pending initialization value.
1908 // different kinds of declarations: 'var' initializations are simply
1909 // assignments (with all the consequences if they are inside a 'with'
1910 // statement - they may change a 'with' object property). Constant
1911 // initializations always assign to the declared constant which is
1912 // always at the function scope level. This is only relevant for
1913 // dynamically looked-up variables and constants (the start context
1914 // for constant lookups is always the function context, while it is
1915 // the top context for var declared variables). Sigh...
1916 // For 'let' and 'const' declared variables in harmony mode the
1917 // initialization is in the same scope as the declaration. Thus dynamic
1918 // lookups are unnecessary even if the block scope is inside a with.
1919 if (value != NULL) { 1937 if (value != NULL) {
1938 ASSERT(mode == VAR);
1939 // 'var' initializations are simply assignments (with all the consequences
1940 // if they are inside a 'with' statement - they may change a 'with' object
1941 // property).
1920 VariableProxy* proxy = initialization_scope->NewUnresolved(name); 1942 VariableProxy* proxy = initialization_scope->NewUnresolved(name);
1921 Assignment* assignment = 1943 Assignment* assignment =
1922 new(zone()) Assignment(isolate(), init_op, proxy, value, position); 1944 new(zone()) Assignment(isolate(), init_op, proxy, value, position);
1923 block->AddStatement(new(zone()) ExpressionStatement(assignment)); 1945 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1924 } 1946 }
1925 1947
1926 if (fni_ != NULL) fni_->Leave(); 1948 if (fni_ != NULL) fni_->Leave();
1927 } while (peek() == Token::COMMA); 1949 } while (peek() == Token::COMMA);
1928 1950
1929 // If there was a single non-const declaration, return it in the output 1951 // If there was a single non-const declaration, return it in the output
(...skipping 3488 matching lines...) Expand 10 before | Expand all | Expand 10 after
5418 result = parser.ParseProgram(source, 5440 result = parser.ParseProgram(source,
5419 info->is_global(), 5441 info->is_global(),
5420 info->strict_mode_flag()); 5442 info->strict_mode_flag());
5421 } 5443 }
5422 } 5444 }
5423 info->SetFunction(result); 5445 info->SetFunction(result);
5424 return (result != NULL); 5446 return (result != NULL);
5425 } 5447 }
5426 5448
5427 } } // namespace v8::internal 5449 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/contexts.cc ('k') | src/runtime.cc » ('j') | src/runtime.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698