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

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

Issue 2636543002: PreParser scope analysis: sloppy block funcs. (Closed)
Patch Set: proactive code review Created 3 years, 11 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/parsing/parser.h » ('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/ast/ast.h" 10 #include "src/ast/ast.h"
11 #include "src/bootstrapper.h" 11 #include "src/bootstrapper.h"
12 #include "src/counters.h" 12 #include "src/counters.h"
13 #include "src/messages.h" 13 #include "src/messages.h"
14 #include "src/objects-inl.h" 14 #include "src/objects-inl.h"
15 #include "src/objects/module-info.h" 15 #include "src/objects/module-info.h"
16 #include "src/parsing/parse-info.h" 16 #include "src/parsing/parse-info.h"
17 17
18 namespace v8 { 18 namespace v8 {
19 namespace internal { 19 namespace internal {
20 20
21 namespace { 21 namespace {
22 void* kDummyPreParserVariable = reinterpret_cast<void*>(0x1); 22 void* kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
23 void* kDummyPreParserLexicalVariable = reinterpret_cast<void*>(0x2);
24
25 bool IsLexical(Variable* variable) {
26 if (variable == kDummyPreParserLexicalVariable) return true;
27 if (variable == kDummyPreParserVariable) return false;
28 return IsLexicalVariableMode(variable->mode());
29 }
30
23 } // namespace 31 } // namespace
24 32
25 // ---------------------------------------------------------------------------- 33 // ----------------------------------------------------------------------------
26 // Implementation of LocalsMap 34 // Implementation of LocalsMap
27 // 35 //
28 // Note: We are storing the handle locations as key values in the hash map. 36 // Note: We are storing the handle locations as key values in the hash map.
29 // When inserting a new variable via Declare(), we rely on the fact that 37 // When inserting a new variable via Declare(), we rely on the fact that
30 // the handle location remains alive for the duration of that variable 38 // the handle location remains alive for the duration of that variable
31 // use. Because a Variable holding a handle with the same location exists 39 // use. Because a Variable holding a handle with the same location exists
32 // this is ensured. 40 // this is ensured.
(...skipping 16 matching lines...) Expand all
49 if (added) *added = p->value == nullptr; 57 if (added) *added = p->value == nullptr;
50 if (p->value == nullptr) { 58 if (p->value == nullptr) {
51 // The variable has not been declared yet -> insert it. 59 // The variable has not been declared yet -> insert it.
52 DCHECK_EQ(name, p->key); 60 DCHECK_EQ(name, p->key);
53 p->value = new (zone) Variable(scope, name, mode, kind, initialization_flag, 61 p->value = new (zone) Variable(scope, name, mode, kind, initialization_flag,
54 maybe_assigned_flag); 62 maybe_assigned_flag);
55 } 63 }
56 return reinterpret_cast<Variable*>(p->value); 64 return reinterpret_cast<Variable*>(p->value);
57 } 65 }
58 66
59 void VariableMap::DeclareName(Zone* zone, const AstRawString* name) { 67 void VariableMap::DeclareName(Zone* zone, const AstRawString* name,
68 VariableMode mode) {
60 Entry* p = 69 Entry* p =
61 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), 70 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
62 ZoneAllocationPolicy(zone)); 71 ZoneAllocationPolicy(zone));
63 if (p->value == nullptr) { 72 if (p->value == nullptr) {
64 // The variable has not been declared yet -> insert it. 73 // The variable has not been declared yet -> insert it.
65 DCHECK_EQ(name, p->key); 74 DCHECK_EQ(name, p->key);
66 p->value = kDummyPreParserVariable; 75 p->value =
76 mode == VAR ? kDummyPreParserVariable : kDummyPreParserLexicalVariable;
67 } 77 }
68 } 78 }
69 79
70 void VariableMap::Remove(Variable* var) { 80 void VariableMap::Remove(Variable* var) {
71 const AstRawString* name = var->raw_name(); 81 const AstRawString* name = var->raw_name();
72 ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->hash()); 82 ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->hash());
73 } 83 }
74 84
75 void VariableMap::Add(Zone* zone, Variable* var) { 85 void VariableMap::Add(Zone* zone, Variable* var) {
76 const AstRawString* name = var->raw_name(); 86 const AstRawString* name = var->raw_name();
77 Entry* p = 87 Entry* p =
78 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), 88 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
79 ZoneAllocationPolicy(zone)); 89 ZoneAllocationPolicy(zone));
80 DCHECK_NULL(p->value); 90 DCHECK_NULL(p->value);
81 DCHECK_EQ(name, p->key); 91 DCHECK_EQ(name, p->key);
82 p->value = var; 92 p->value = var;
83 } 93 }
84 94
85 Variable* VariableMap::Lookup(const AstRawString* name) { 95 Variable* VariableMap::Lookup(const AstRawString* name) {
86 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash()); 96 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash());
87 if (p != NULL) { 97 if (p != NULL) {
88 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); 98 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
89 DCHECK(p->value != NULL); 99 DCHECK(p->value != NULL);
90 return reinterpret_cast<Variable*>(p->value); 100 return reinterpret_cast<Variable*>(p->value);
91 } 101 }
92 return NULL; 102 return NULL;
93 } 103 }
94 104
105 void SloppyBlockFunctionMap::Delegate::set_statement(Statement* statement) {
106 if (statement_ != nullptr) {
107 statement_->set_statement(statement);
108 }
109 }
110
95 SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone) 111 SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone)
96 : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {} 112 : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
97 113
98 void SloppyBlockFunctionMap::Declare(Zone* zone, const AstRawString* name, 114 void SloppyBlockFunctionMap::Declare(
99 SloppyBlockFunctionStatement* stmt) { 115 Zone* zone, const AstRawString* name,
116 SloppyBlockFunctionMap::Delegate* delegate) {
100 // AstRawStrings are unambiguous, i.e., the same string is always represented 117 // AstRawStrings are unambiguous, i.e., the same string is always represented
101 // by the same AstRawString*. 118 // by the same AstRawString*.
102 Entry* p = 119 Entry* p =
103 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), 120 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
104 ZoneAllocationPolicy(zone)); 121 ZoneAllocationPolicy(zone));
105 stmt->set_next(static_cast<SloppyBlockFunctionStatement*>(p->value)); 122 delegate->set_next(static_cast<SloppyBlockFunctionMap::Delegate*>(p->value));
106 p->value = stmt; 123 p->value = delegate;
107 } 124 }
108 125
109
110 // ---------------------------------------------------------------------------- 126 // ----------------------------------------------------------------------------
111 // Implementation of Scope 127 // Implementation of Scope
112 128
113 Scope::Scope(Zone* zone) 129 Scope::Scope(Zone* zone)
114 : zone_(zone), 130 : zone_(zone),
115 outer_scope_(nullptr), 131 outer_scope_(nullptr),
116 variables_(zone), 132 variables_(zone),
117 scope_type_(SCRIPT_SCOPE) { 133 scope_type_(SCRIPT_SCOPE) {
118 SetDefaults(); 134 SetDefaults();
119 } 135 }
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 457
442 const ModuleScope* Scope::AsModuleScope() const { 458 const ModuleScope* Scope::AsModuleScope() const {
443 DCHECK(is_module_scope()); 459 DCHECK(is_module_scope());
444 return static_cast<const ModuleScope*>(this); 460 return static_cast<const ModuleScope*>(this);
445 } 461 }
446 462
447 int Scope::num_parameters() const { 463 int Scope::num_parameters() const {
448 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0; 464 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0;
449 } 465 }
450 466
467 void DeclarationScope::DeclareSloppyBlockFunction(
468 const AstRawString* name, Scope* scope,
469 SloppyBlockFunctionStatement* statement) {
470 auto* delegate =
471 new (zone()) SloppyBlockFunctionMap::Delegate(scope, statement);
472 sloppy_block_function_map_.Declare(zone(), name, delegate);
473 }
474
451 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) { 475 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
452 DCHECK(is_sloppy(language_mode())); 476 DCHECK(is_sloppy(language_mode()));
453 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() || 477 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
454 (is_block_scope() && outer_scope()->is_function_scope())); 478 (is_block_scope() && outer_scope()->is_function_scope()));
455 DCHECK(HasSimpleParameters() || is_block_scope()); 479 DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
480 DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_);
481
456 bool has_simple_parameters = HasSimpleParameters(); 482 bool has_simple_parameters = HasSimpleParameters();
457 // For each variable which is used as a function declaration in a sloppy 483 // For each variable which is used as a function declaration in a sloppy
458 // block, 484 // block,
459 SloppyBlockFunctionMap* map = sloppy_block_function_map(); 485 SloppyBlockFunctionMap* map = sloppy_block_function_map();
460 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { 486 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
461 AstRawString* name = static_cast<AstRawString*>(p->key); 487 AstRawString* name = static_cast<AstRawString*>(p->key);
462 488
463 // If the variable wouldn't conflict with a lexical declaration 489 // If the variable wouldn't conflict with a lexical declaration
464 // or parameter, 490 // or parameter,
465 491
(...skipping 11 matching lines...) Expand all
477 } 503 }
478 } else { 504 } else {
479 if (IsDeclaredParameter(name)) { 505 if (IsDeclaredParameter(name)) {
480 continue; 506 continue;
481 } 507 }
482 } 508 }
483 509
484 bool var_created = false; 510 bool var_created = false;
485 511
486 // Write in assignments to var for each block-scoped function declaration 512 // Write in assignments to var for each block-scoped function declaration
487 auto delegates = static_cast<SloppyBlockFunctionStatement*>(p->value); 513 auto delegates = static_cast<SloppyBlockFunctionMap::Delegate*>(p->value);
488 514
489 DeclarationScope* decl_scope = this; 515 DeclarationScope* decl_scope = this;
490 while (decl_scope->is_eval_scope()) { 516 while (decl_scope->is_eval_scope()) {
491 decl_scope = decl_scope->outer_scope()->GetDeclarationScope(); 517 decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
492 } 518 }
493 Scope* outer_scope = decl_scope->outer_scope(); 519 Scope* outer_scope = decl_scope->outer_scope();
494 520
495 for (SloppyBlockFunctionStatement* delegate = delegates; 521 for (SloppyBlockFunctionMap::Delegate* delegate = delegates;
496 delegate != nullptr; delegate = delegate->next()) { 522 delegate != nullptr; delegate = delegate->next()) {
497 // Check if there's a conflict with a lexical declaration 523 // Check if there's a conflict with a lexical declaration
498 Scope* query_scope = delegate->scope()->outer_scope(); 524 Scope* query_scope = delegate->scope()->outer_scope();
499 Variable* var = nullptr; 525 Variable* var = nullptr;
500 bool should_hoist = true; 526 bool should_hoist = true;
501 527
502 // Note that we perform this loop for each delegate named 'name', 528 // Note that we perform this loop for each delegate named 'name',
503 // which may duplicate work if those delegates share scopes. 529 // which may duplicate work if those delegates share scopes.
504 // It is not sufficient to just do a Lookup on query_scope: for 530 // It is not sufficient to just do a Lookup on query_scope: for
505 // example, that does not prevent hoisting of the function in 531 // example, that does not prevent hoisting of the function in
506 // `{ let e; try {} catch (e) { function e(){} } }` 532 // `{ let e; try {} catch (e) { function e(){} } }`
507 do { 533 do {
508 var = query_scope->LookupLocal(name); 534 var = query_scope->LookupLocal(name);
509 if (var != nullptr && IsLexicalVariableMode(var->mode())) { 535 if (var != nullptr && IsLexical(var)) {
510 should_hoist = false; 536 should_hoist = false;
511 break; 537 break;
512 } 538 }
513 query_scope = query_scope->outer_scope(); 539 query_scope = query_scope->outer_scope();
514 } while (query_scope != outer_scope); 540 } while (query_scope != outer_scope);
515 541
516 if (!should_hoist) continue; 542 if (!should_hoist) continue;
517 543
518 // Declare a var-style binding for the function in the outer scope 544 // Declare a var-style binding for the function in the outer scope
519 if (!var_created) { 545 if (!var_created) {
520 var_created = true; 546 var_created = true;
521 VariableProxy* proxy = factory->NewVariableProxy(name, NORMAL_VARIABLE); 547 if (factory) {
522 Declaration* declaration = 548 VariableProxy* proxy =
523 factory->NewVariableDeclaration(proxy, this, kNoSourcePosition); 549 factory->NewVariableProxy(name, NORMAL_VARIABLE);
524 // Based on the preceding check, it doesn't matter what we pass as 550 auto declaration =
525 // allow_harmony_restrictive_generators and 551 factory->NewVariableDeclaration(proxy, this, kNoSourcePosition);
526 // sloppy_mode_block_scope_function_redefinition. 552 // Based on the preceding check, it doesn't matter what we pass as
527 bool ok = true; 553 // allow_harmony_restrictive_generators and
528 DeclareVariable(declaration, VAR, 554 // sloppy_mode_block_scope_function_redefinition.
529 Variable::DefaultInitializationFlag(VAR), false, 555 bool ok = true;
530 nullptr, &ok); 556 DeclareVariable(declaration, VAR,
531 CHECK(ok); // Based on the preceding check, this should not fail 557 Variable::DefaultInitializationFlag(VAR), false,
558 nullptr, &ok);
559 CHECK(ok); // Based on the preceding check, this should not fail
560 } else {
561 DeclareVariableName(name, VAR);
562 }
532 } 563 }
533 564
534 Expression* assignment = factory->NewAssignment( 565 if (factory) {
535 Token::ASSIGN, NewUnresolved(factory, name), 566 Expression* assignment = factory->NewAssignment(
536 delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition); 567 Token::ASSIGN, NewUnresolved(factory, name),
537 Statement* statement = 568 delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition);
538 factory->NewExpressionStatement(assignment, kNoSourcePosition); 569 Statement* statement =
539 delegate->set_statement(statement); 570 factory->NewExpressionStatement(assignment, kNoSourcePosition);
571 delegate->set_statement(statement);
572 }
540 } 573 }
541 } 574 }
542 } 575 }
543 576
544 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) { 577 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) {
545 RuntimeCallTimerScope runtimeTimer(info->isolate(), 578 RuntimeCallTimerScope runtimeTimer(info->isolate(),
546 &RuntimeCallStats::CompileScopeAnalysis); 579 &RuntimeCallStats::CompileScopeAnalysis);
547 DCHECK(info->literal() != NULL); 580 DCHECK(info->literal() != NULL);
548 DeclarationScope* scope = info->literal()->scope(); 581 DeclarationScope* scope = info->literal()->scope();
549 582
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 DCHECK(!is_eval_scope()); 1074 DCHECK(!is_eval_scope());
1042 // Unlike DeclareVariable, DeclareVariableName allows declaring variables in 1075 // Unlike DeclareVariable, DeclareVariableName allows declaring variables in
1043 // catch scopes: Parser::RewriteCatchPattern bypasses DeclareVariable by 1076 // catch scopes: Parser::RewriteCatchPattern bypasses DeclareVariable by
1044 // calling DeclareLocal directly, and it doesn't make sense to add a similar 1077 // calling DeclareLocal directly, and it doesn't make sense to add a similar
1045 // bypass mechanism for PreParser. 1078 // bypass mechanism for PreParser.
1046 DCHECK(is_declaration_scope() || (IsLexicalVariableMode(mode) && 1079 DCHECK(is_declaration_scope() || (IsLexicalVariableMode(mode) &&
1047 (is_block_scope() || is_catch_scope()))); 1080 (is_block_scope() || is_catch_scope())));
1048 DCHECK(scope_info_.is_null()); 1081 DCHECK(scope_info_.is_null());
1049 1082
1050 // Declare the variable in the declaration scope. 1083 // Declare the variable in the declaration scope.
1051 variables_.DeclareName(zone(), name); 1084 variables_.DeclareName(zone(), name, mode);
1052 } 1085 }
1053 1086
1054 VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory, 1087 VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory,
1055 const AstRawString* name, 1088 const AstRawString* name,
1056 int start_position, VariableKind kind) { 1089 int start_position, VariableKind kind) {
1057 // Note that we must not share the unresolved variables with 1090 // Note that we must not share the unresolved variables with
1058 // the same name because they may be removed selectively via 1091 // the same name because they may be removed selectively via
1059 // RemoveUnresolved(). 1092 // RemoveUnresolved().
1060 DCHECK(!already_resolved_); 1093 DCHECK(!already_resolved_);
1061 DCHECK_EQ(factory->zone(), zone()); 1094 DCHECK_EQ(factory->zone(), zone());
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 } 1673 }
1641 1674
1642 DCHECK(!is_script_scope()); 1675 DCHECK(!is_script_scope());
1643 1676
1644 var = outer_scope_->LookupRecursive(proxy, outer_scope_end); 1677 var = outer_scope_->LookupRecursive(proxy, outer_scope_end);
1645 1678
1646 // The variable could not be resolved statically. 1679 // The variable could not be resolved statically.
1647 if (var == nullptr) return var; 1680 if (var == nullptr) return var;
1648 1681
1649 // TODO(marja): Separate LookupRecursive for preparsed scopes better. 1682 // TODO(marja): Separate LookupRecursive for preparsed scopes better.
1650 if (var == kDummyPreParserVariable) { 1683 if (var == kDummyPreParserVariable || var == kDummyPreParserLexicalVariable) {
1651 DCHECK(GetDeclarationScope()->is_being_lazily_parsed()); 1684 DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1652 DCHECK(FLAG_lazy_inner_functions); 1685 DCHECK(FLAG_lazy_inner_functions);
1653 return var; 1686 return var;
1654 } 1687 }
1655 1688
1656 if (is_function_scope() && !var->is_dynamic()) { 1689 if (is_function_scope() && !var->is_dynamic()) {
1657 var->ForceContextAllocation(); 1690 var->ForceContextAllocation();
1658 } 1691 }
1659 // "this" can't be shadowed by "eval"-introduced bindings or by "with" 1692 // "this" can't be shadowed by "eval"-introduced bindings or by "with"
1660 // scopes. 1693 // scopes.
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1838 : this; 1871 : this;
1839 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; 1872 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
1840 proxy = next) { 1873 proxy = next) {
1841 next = proxy->next_unresolved(); 1874 next = proxy->next_unresolved();
1842 DCHECK(!proxy->is_resolved()); 1875 DCHECK(!proxy->is_resolved());
1843 Variable* var = 1876 Variable* var =
1844 lookup->LookupRecursive(proxy, max_outer_scope->outer_scope()); 1877 lookup->LookupRecursive(proxy, max_outer_scope->outer_scope());
1845 if (var == nullptr) { 1878 if (var == nullptr) {
1846 proxy->set_next_unresolved(stack); 1879 proxy->set_next_unresolved(stack);
1847 stack = proxy; 1880 stack = proxy;
1848 } else if (var != kDummyPreParserVariable) { 1881 } else if (var != kDummyPreParserVariable &&
1882 var != kDummyPreParserLexicalVariable) {
1849 if (info != nullptr) { 1883 if (info != nullptr) {
1850 // In this case we need to leave scopes in a way that they can be 1884 // In this case we need to leave scopes in a way that they can be
1851 // allocated. If we resolved variables from lazy parsed scopes, we need 1885 // allocated. If we resolved variables from lazy parsed scopes, we need
1852 // to context allocate the var. 1886 // to context allocate the var.
1853 ResolveTo(info, proxy, var); 1887 ResolveTo(info, proxy, var);
1854 if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation(); 1888 if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
1855 } else { 1889 } else {
1856 var->set_is_used(); 1890 var->set_is_used();
1857 } 1891 }
1858 } 1892 }
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 Variable* function = 2168 Variable* function =
2135 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; 2169 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2136 bool is_function_var_in_context = 2170 bool is_function_var_in_context =
2137 function != nullptr && function->IsContextSlot(); 2171 function != nullptr && function->IsContextSlot();
2138 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 2172 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2139 (is_function_var_in_context ? 1 : 0); 2173 (is_function_var_in_context ? 1 : 0);
2140 } 2174 }
2141 2175
2142 } // namespace internal 2176 } // namespace internal
2143 } // namespace v8 2177 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | src/parsing/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698