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

Side by Side Diff: src/parser.cc

Issue 10872084: Allocate block-scoped global bindings to global context. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 // Compute the parsing mode. 617 // Compute the parsing mode.
618 Mode mode = (FLAG_lazy && allow_lazy_) ? PARSE_LAZILY : PARSE_EAGERLY; 618 Mode mode = (FLAG_lazy && allow_lazy_) ? PARSE_LAZILY : PARSE_EAGERLY;
619 if (allow_natives_syntax_ || extension_ != NULL) mode = PARSE_EAGERLY; 619 if (allow_natives_syntax_ || extension_ != NULL) mode = PARSE_EAGERLY;
620 ParsingModeScope parsing_mode(this, mode); 620 ParsingModeScope parsing_mode(this, mode);
621 621
622 Handle<String> no_name = isolate()->factory()->empty_symbol(); 622 Handle<String> no_name = isolate()->factory()->empty_symbol();
623 623
624 FunctionLiteral* result = NULL; 624 FunctionLiteral* result = NULL;
625 { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); 625 { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
626 info->SetGlobalScope(scope); 626 info->SetGlobalScope(scope);
627 if (!info->context().is_null()) {
628 scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
629 }
627 if (info->is_eval()) { 630 if (info->is_eval()) {
628 Handle<SharedFunctionInfo> shared = info->shared_info();
629 if (!info->is_global() && (shared.is_null() || shared->is_function())) {
630 scope = Scope::DeserializeScopeChain(*info->calling_context(), scope,
631 zone());
632 }
633 if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) { 631 if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
634 scope = NewScope(scope, EVAL_SCOPE); 632 scope = NewScope(scope, EVAL_SCOPE);
635 } 633 }
634 } else if (info->is_global()) {
635 scope = NewScope(scope, GLOBAL_SCOPE);
636 } 636 }
637 scope->set_start_position(0); 637 scope->set_start_position(0);
638 scope->set_end_position(source->length()); 638 scope->set_end_position(source->length());
639 FunctionState function_state(this, scope, isolate()); 639
640 FunctionState function_state(this, scope, isolate()); // Enters 'scope'.
640 top_scope_->SetLanguageMode(info->language_mode()); 641 top_scope_->SetLanguageMode(info->language_mode());
641 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); 642 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
642 bool ok = true; 643 bool ok = true;
643 int beg_loc = scanner().location().beg_pos; 644 int beg_loc = scanner().location().beg_pos;
644 ParseSourceElements(body, Token::EOS, info->is_eval(), &ok); 645 ParseSourceElements(body, Token::EOS, info->is_eval(), &ok);
645 if (ok && !top_scope_->is_classic_mode()) { 646 if (ok && !top_scope_->is_classic_mode()) {
646 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok); 647 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
647 } 648 }
648 649
649 if (ok && is_extended_mode()) { 650 if (ok && is_extended_mode()) {
(...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1780 // will be added to the scope so that the declaration can be added 1781 // will be added to the scope so that the declaration can be added
1781 // to the corresponding activation frame at runtime if necessary. 1782 // to the corresponding activation frame at runtime if necessary.
1782 // For instance declarations inside an eval scope need to be added 1783 // For instance declarations inside an eval scope need to be added
1783 // to the calling function context. 1784 // to the calling function context.
1784 // Similarly, strict mode eval scope does not leak variable declarations to 1785 // Similarly, strict mode eval scope does not leak variable declarations to
1785 // the caller's scope so we declare all locals, too. 1786 // the caller's scope so we declare all locals, too.
1786 if (declaration_scope->is_function_scope() || 1787 if (declaration_scope->is_function_scope() ||
1787 declaration_scope->is_strict_or_extended_eval_scope() || 1788 declaration_scope->is_strict_or_extended_eval_scope() ||
1788 declaration_scope->is_block_scope() || 1789 declaration_scope->is_block_scope() ||
1789 declaration_scope->is_module_scope() || 1790 declaration_scope->is_module_scope() ||
1790 declaration->AsModuleDeclaration() != NULL) { 1791 declaration_scope->is_global_scope()) {
1791 // Declare the variable in the declaration scope. 1792 // Declare the variable in the declaration scope.
1792 var = declaration_scope->LocalLookup(name); 1793 // For the global scope, we have to check for collisions with earlier
1794 // (i.e., enclosing) global scopes, to maintain the illusion of a single
1795 // global scope.
1796 var = declaration_scope->is_global_scope()
1797 ? declaration_scope->Lookup(name)
1798 : declaration_scope->LocalLookup(name);
1793 if (var == NULL) { 1799 if (var == NULL) {
1794 // Declare the name. 1800 // Declare the name.
1795 var = declaration_scope->DeclareLocal( 1801 var = declaration_scope->DeclareLocal(
1796 name, mode, declaration->initialization(), proxy->interface()); 1802 name, mode, declaration->initialization(), proxy->interface());
1797 } else { 1803 } else if ((mode != VAR || var->mode() != VAR) &&
1804 (!declaration_scope->is_global_scope() ||
1805 (mode != VAR && mode != CONST) ||
Sven Panne 2012/08/28 07:35:00 o_O
rossberg 2012/08/28 11:09:39 You gotta love the beauty of semantic incoherence
1806 (var->mode() != VAR && var->mode() != CONST))) {
1798 // The name was declared in this scope before; check for conflicting 1807 // The name was declared in this scope before; check for conflicting
1799 // re-declarations. We have a conflict if either of the declarations is 1808 // re-declarations. We have a conflict if either of the declarations is
1800 // not a var. There is similar code in runtime.cc in the Declare 1809 // not a var (in the global scope, we also have to ignore legacy const for
1810 // compatibility). There is similar code in runtime.cc in the Declare
1801 // functions. The function CheckNonConflictingScope checks for conflicting 1811 // functions. The function CheckNonConflictingScope checks for conflicting
1802 // var and let bindings from different scopes whereas this is a check for 1812 // var and let bindings from different scopes whereas this is a check for
1803 // conflicting declarations within the same scope. This check also covers 1813 // conflicting declarations within the same scope. This check also covers
1814 // the special case
1804 // 1815 //
1805 // function () { let x; { var x; } } 1816 // function () { let x; { var x; } }
1806 // 1817 //
1807 // because the var declaration is hoisted to the function scope where 'x' 1818 // because the var declaration is hoisted to the function scope where 'x'
1808 // is already bound. 1819 // is already bound.
1809 if ((mode != VAR) || (var->mode() != VAR)) { 1820 // We only have vars, consts and lets in declarations.
1810 // We only have vars, consts and lets in declarations. 1821 ASSERT(var->mode() == VAR ||
1811 ASSERT(var->mode() == VAR || 1822 var->mode() == CONST ||
1812 var->mode() == CONST || 1823 var->mode() == CONST_HARMONY ||
1813 var->mode() == CONST_HARMONY || 1824 var->mode() == LET);
1814 var->mode() == LET); 1825 if (is_extended_mode()) {
1815 if (is_extended_mode()) { 1826 // In harmony mode we treat re-declarations as early errors. See
1816 // In harmony mode we treat re-declarations as early errors. See 1827 // ES5 16 for a definition of early errors.
1817 // ES5 16 for a definition of early errors. 1828 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1818 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); 1829 const char* elms[2] = { "Variable", *c_string };
1819 const char* elms[2] = { "Variable", *c_string }; 1830 Vector<const char*> args(elms, 2);
1820 Vector<const char*> args(elms, 2); 1831 ReportMessage("redeclaration", args);
1821 ReportMessage("redeclaration", args); 1832 *ok = false;
1822 *ok = false; 1833 return;
1823 return;
1824 }
1825 const char* type = (var->mode() == VAR)
1826 ? "var" : var->is_const_mode() ? "const" : "let";
1827 Handle<String> type_string =
1828 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
1829 Expression* expression =
1830 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
1831 type_string, name);
1832 declaration_scope->SetIllegalRedeclaration(expression);
1833 } 1834 }
1835 const char* type =
1836 (var->mode() == VAR) ? "var" : var->is_const_mode() ? "const" : "let";
1837 Handle<String> type_string =
1838 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
1839 Expression* expression =
1840 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
1841 type_string, name);
1842 declaration_scope->SetIllegalRedeclaration(expression);
1834 } 1843 }
1835 } 1844 }
1836 1845
1837 // We add a declaration node for every declaration. The compiler 1846 // We add a declaration node for every declaration. The compiler
1838 // will only generate code if necessary. In particular, declarations 1847 // will only generate code if necessary. In particular, declarations
1839 // for inner local variables that do not represent functions won't 1848 // for inner local variables that do not represent functions won't
1840 // result in any generated code. 1849 // result in any generated code.
1841 // 1850 //
1842 // Note that we always add an unresolved proxy even if it's not 1851 // Note that we always add an unresolved proxy even if it's not
1843 // used, simply because we don't know in this method (w/o extra 1852 // used, simply because we don't know in this method (w/o extra
1844 // parameters) if the proxy is needed or not. The proxy will be 1853 // parameters) if the proxy is needed or not. The proxy will be
1845 // bound during variable resolution time unless it was pre-bound 1854 // bound during variable resolution time unless it was pre-bound
1846 // below. 1855 // below.
1847 // 1856 //
1848 // WARNING: This will lead to multiple declaration nodes for the 1857 // WARNING: This will lead to multiple declaration nodes for the
1849 // same variable if it is declared several times. This is not a 1858 // same variable if it is declared several times. This is not a
1850 // semantic issue as long as we keep the source order, but it may be 1859 // semantic issue as long as we keep the source order, but it may be
1851 // a performance issue since it may lead to repeated 1860 // a performance issue since it may lead to repeated
1852 // Runtime::DeclareContextSlot() calls. 1861 // Runtime::DeclareContextSlot() calls.
1853 declaration_scope->AddDeclaration(declaration); 1862 declaration_scope->AddDeclaration(declaration);
1854 1863
1855 if ((mode == CONST || mode == CONST_HARMONY) && 1864 if (mode == CONST && declaration_scope->is_global_scope()) {
1856 declaration_scope->is_global_scope()) {
1857 // For global const variables we bind the proxy to a variable. 1865 // For global const variables we bind the proxy to a variable.
1858 ASSERT(resolve); // should be set by all callers 1866 ASSERT(resolve); // should be set by all callers
1859 Variable::Kind kind = Variable::NORMAL; 1867 Variable::Kind kind = Variable::NORMAL;
1860 var = new(zone()) Variable(declaration_scope, 1868 var = new(zone()) Variable(declaration_scope,
1861 name, 1869 name,
1862 mode, 1870 mode,
1863 true, 1871 true,
1864 kind, 1872 kind,
1865 kNeedsInitialization); 1873 kNeedsInitialization);
1866 } else if (declaration_scope->is_eval_scope() && 1874 } else if (declaration_scope->is_eval_scope() &&
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 int function_token_position = scanner().location().beg_pos; 2005 int function_token_position = scanner().location().beg_pos;
1998 bool is_strict_reserved = false; 2006 bool is_strict_reserved = false;
1999 Handle<String> name = ParseIdentifierOrStrictReservedWord( 2007 Handle<String> name = ParseIdentifierOrStrictReservedWord(
2000 &is_strict_reserved, CHECK_OK); 2008 &is_strict_reserved, CHECK_OK);
2001 FunctionLiteral* fun = ParseFunctionLiteral(name, 2009 FunctionLiteral* fun = ParseFunctionLiteral(name,
2002 is_strict_reserved, 2010 is_strict_reserved,
2003 function_token_position, 2011 function_token_position,
2004 FunctionLiteral::DECLARATION, 2012 FunctionLiteral::DECLARATION,
2005 CHECK_OK); 2013 CHECK_OK);
2006 // Even if we're not at the top-level of the global or a function 2014 // Even if we're not at the top-level of the global or a function
2007 // scope, we treat is as such and introduce the function with it's 2015 // scope, we treat it as such and introduce the function with its
2008 // initial value upon entering the corresponding scope. 2016 // initial value upon entering the corresponding scope.
2009 VariableMode mode = is_extended_mode() ? LET : VAR; 2017 // In extended mode, a function behaves as a lexical binding, except in the
2018 // global scope.
2019 VariableMode mode =
2020 is_extended_mode() && !top_scope_->is_global_scope() ? LET : VAR;
2010 VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue()); 2021 VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
2011 Declaration* declaration = 2022 Declaration* declaration =
2012 factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_); 2023 factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
2013 Declare(declaration, true, CHECK_OK); 2024 Declare(declaration, true, CHECK_OK);
2014 if (names) names->Add(name, zone()); 2025 if (names) names->Add(name, zone());
2015 return factory()->NewEmptyStatement(); 2026 return factory()->NewEmptyStatement();
2016 } 2027 }
2017 2028
2018 2029
2019 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { 2030 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
2322 // executed. 2333 // executed.
2323 // 2334 //
2324 // Executing the variable declaration statement will always 2335 // Executing the variable declaration statement will always
2325 // guarantee to give the global object a "local" variable; a 2336 // guarantee to give the global object a "local" variable; a
2326 // variable defined in the global object and not in any 2337 // variable defined in the global object and not in any
2327 // prototype. This way, global variable declarations can shadow 2338 // prototype. This way, global variable declarations can shadow
2328 // properties in the prototype chain, but only after the variable 2339 // properties in the prototype chain, but only after the variable
2329 // declaration statement has been executed. This is important in 2340 // declaration statement has been executed. This is important in
2330 // browsers where the global object (window) has lots of 2341 // browsers where the global object (window) has lots of
2331 // properties defined in prototype objects. 2342 // properties defined in prototype objects.
2332 if (initialization_scope->is_global_scope()) { 2343 if (initialization_scope->is_global_scope() &&
2344 mode != LET && mode != CONST_HARMONY) {
2333 // Compute the arguments for the runtime call. 2345 // Compute the arguments for the runtime call.
2334 ZoneList<Expression*>* arguments = 2346 ZoneList<Expression*>* arguments =
2335 new(zone()) ZoneList<Expression*>(3, zone()); 2347 new(zone()) ZoneList<Expression*>(3, zone());
2336 // We have at least 1 parameter. 2348 // We have at least 1 parameter.
2337 arguments->Add(factory()->NewLiteral(name), zone()); 2349 arguments->Add(factory()->NewLiteral(name), zone());
2338 CallRuntime* initialize; 2350 CallRuntime* initialize;
2339 2351
2340 if (is_const) { 2352 if (is_const) {
2341 arguments->Add(value, zone()); 2353 arguments->Add(value, zone());
2342 value = NULL; // zap the value to avoid the unnecessary assignment 2354 value = NULL; // zap the value to avoid the unnecessary assignment
(...skipping 3753 matching lines...) Expand 10 before | Expand all | Expand 10 after
6096 ASSERT(info->isolate()->has_pending_exception()); 6108 ASSERT(info->isolate()->has_pending_exception());
6097 } else { 6109 } else {
6098 result = parser.ParseProgram(); 6110 result = parser.ParseProgram();
6099 } 6111 }
6100 } 6112 }
6101 info->SetFunction(result); 6113 info->SetFunction(result);
6102 return (result != NULL); 6114 return (result != NULL);
6103 } 6115 }
6104 6116
6105 } } // namespace v8::internal 6117 } } // namespace v8::internal
OLDNEW
« src/objects.cc ('K') | « src/objects-inl.h ('k') | src/rewriter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698