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/parser.cc

Issue 1110473003: Eagerly declare eval scopes, even for sloppy scopes (Closed) Base URL: https://chromium.googlesource.com/v8/v8@master
Patch Set: Fix nits Created 5 years, 8 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/parser.h ('k') | src/runtime/runtime-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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 } 954 }
955 955
956 956
957 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { 957 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
958 // Note that this function can be called from the main thread or from a 958 // Note that this function can be called from the main thread or from a
959 // background thread. We should not access anything Isolate / heap dependent 959 // background thread. We should not access anything Isolate / heap dependent
960 // via ParseInfo, and also not pass it forward. 960 // via ParseInfo, and also not pass it forward.
961 DCHECK(scope_ == NULL); 961 DCHECK(scope_ == NULL);
962 DCHECK(target_stack_ == NULL); 962 DCHECK(target_stack_ == NULL);
963 963
964 Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY;
965 if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY;
966
964 FunctionLiteral* result = NULL; 967 FunctionLiteral* result = NULL;
965 { 968 {
966 Scope* scope = NewScope(scope_, SCRIPT_SCOPE); 969 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
967 info->set_script_scope(scope); 970 info->set_script_scope(scope);
968 if (!info->context().is_null() && !info->context()->IsNativeContext()) { 971 if (!info->context().is_null() && !info->context()->IsNativeContext()) {
969 scope = Scope::DeserializeScopeChain(info->isolate(), zone(), 972 scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
970 *info->context(), scope); 973 *info->context(), scope);
971 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this 974 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
972 // means the Parser cannot operate independent of the V8 heap. Tell the 975 // means the Parser cannot operate independent of the V8 heap. Tell the
973 // string table to internalize strings and values right after they're 976 // string table to internalize strings and values right after they're
974 // created. This kind of parsing can only be done in the main thread. 977 // created. This kind of parsing can only be done in the main thread.
975 DCHECK(parsing_on_main_thread_); 978 DCHECK(parsing_on_main_thread_);
976 ast_value_factory()->Internalize(info->isolate()); 979 ast_value_factory()->Internalize(info->isolate());
977 } 980 }
978 original_scope_ = scope; 981 original_scope_ = scope;
979 if (info->is_eval()) { 982 if (info->is_eval()) {
980 if (!scope->is_script_scope() || is_strict(info->language_mode())) { 983 if (!scope->is_script_scope() || is_strict(info->language_mode())) {
981 scope = NewScope(scope, EVAL_SCOPE); 984 parsing_mode = PARSE_EAGERLY;
982 } 985 }
986 scope = NewScope(scope, EVAL_SCOPE);
983 } else if (info->is_module()) { 987 } else if (info->is_module()) {
984 scope = NewScope(scope, MODULE_SCOPE); 988 scope = NewScope(scope, MODULE_SCOPE);
985 } 989 }
986 990
987 scope->set_start_position(0); 991 scope->set_start_position(0);
988 992
989 // Compute the parsing mode. 993 // Enter 'scope' with the given parsing mode.
990 Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY; 994 ParsingModeScope parsing_mode_scope(this, parsing_mode);
991 if (allow_natives() || extension_ != NULL || scope->is_eval_scope()) {
992 mode = PARSE_EAGERLY;
993 }
994 ParsingModeScope parsing_mode(this, mode);
995
996 // Enters 'scope'.
997 AstNodeFactory function_factory(ast_value_factory()); 995 AstNodeFactory function_factory(ast_value_factory());
998 FunctionState function_state(&function_state_, &scope_, scope, 996 FunctionState function_state(&function_state_, &scope_, scope,
999 kNormalFunction, &function_factory); 997 kNormalFunction, &function_factory);
1000 998
1001 scope_->SetLanguageMode(info->language_mode()); 999 scope_->SetLanguageMode(info->language_mode());
1002 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); 1000 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
1003 bool ok = true; 1001 bool ok = true;
1004 int beg_pos = scanner()->location().beg_pos; 1002 int beg_pos = scanner()->location().beg_pos;
1005 if (info->is_module()) { 1003 if (info->is_module()) {
1006 DCHECK(allow_harmony_modules()); 1004 DCHECK(allow_harmony_modules());
1007 ParseModuleItemList(body, &ok); 1005 ParseModuleItemList(body, &ok);
1008 } else { 1006 } else {
1009 Scope* eval_scope = nullptr; 1007 ParseStatementList(body, Token::EOS, &ok);
1010 ParseStatementList(body, Token::EOS, info->is_eval(), &eval_scope, &ok);
1011 if (eval_scope != nullptr)
1012 eval_scope->set_end_position(scanner()->peek_location().beg_pos);
1013 } 1008 }
1014 1009
1015 // The parser will peek but not consume EOS. Our scope logically goes all 1010 // The parser will peek but not consume EOS. Our scope logically goes all
1016 // the way to the EOS, though. 1011 // the way to the EOS, though.
1017 scope->set_end_position(scanner()->peek_location().beg_pos); 1012 scope->set_end_position(scanner()->peek_location().beg_pos);
1018 1013
1019 if (ok && is_strict(language_mode())) { 1014 if (ok && is_strict(language_mode())) {
1020 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); 1015 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
1021 CheckConflictingVarDeclarations(scope_, &ok); 1016 CheckConflictingVarDeclarations(scope_, &ok);
1022 } 1017 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 1183
1189 if (result != NULL) { 1184 if (result != NULL) {
1190 Handle<String> inferred_name(shared_info->inferred_name()); 1185 Handle<String> inferred_name(shared_info->inferred_name());
1191 result->set_inferred_name(inferred_name); 1186 result->set_inferred_name(inferred_name);
1192 } 1187 }
1193 return result; 1188 return result;
1194 } 1189 }
1195 1190
1196 1191
1197 void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token, 1192 void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
1198 bool is_eval, Scope** eval_scope, bool* ok) { 1193 bool* ok) {
1199 // StatementList :: 1194 // StatementList ::
1200 // (StatementListItem)* <end_token> 1195 // (StatementListItem)* <end_token>
1201 1196
1202 // Allocate a target stack to use for this set of source 1197 // Allocate a target stack to use for this set of source
1203 // elements. This way, all scripts and functions get their own 1198 // elements. This way, all scripts and functions get their own
1204 // target stack thus avoiding illegal breaks and continues across 1199 // target stack thus avoiding illegal breaks and continues across
1205 // functions. 1200 // functions.
1206 TargetScope scope(&this->target_stack_); 1201 TargetScope scope(&this->target_stack_);
1207 1202
1208 DCHECK(body != NULL); 1203 DCHECK(body != NULL);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1260 bool use_strong_found = 1255 bool use_strong_found =
1261 allow_strong_mode() && 1256 allow_strong_mode() &&
1262 literal->raw_value()->AsString() == 1257 literal->raw_value()->AsString() ==
1263 ast_value_factory()->use_strong_string() && 1258 ast_value_factory()->use_strong_string() &&
1264 token_loc.end_pos - token_loc.beg_pos == 1259 token_loc.end_pos - token_loc.beg_pos ==
1265 ast_value_factory()->use_strong_string()->length() + 2; 1260 ast_value_factory()->use_strong_string()->length() + 2;
1266 if (use_strict_found || use_strong_found) { 1261 if (use_strict_found || use_strong_found) {
1267 // Strong mode implies strict mode. If there are several "use strict" 1262 // Strong mode implies strict mode. If there are several "use strict"
1268 // / "use strong" directives, do the strict mode changes only once. 1263 // / "use strong" directives, do the strict mode changes only once.
1269 if (is_sloppy(scope_->language_mode())) { 1264 if (is_sloppy(scope_->language_mode())) {
1270 // TODO(mstarzinger): Global strict eval calls, need their own scope
1271 // as specified in ES5 10.4.2(3). The correct fix would be to always
1272 // add this scope in DoParseProgram(), but that requires adaptations
1273 // all over the code base, so we go with a quick-fix for now.
1274 // In the same manner, we have to patch the parsing mode.
1275 if (is_eval && !scope_->is_eval_scope()) {
1276 DCHECK(scope_->is_script_scope());
1277 Scope* scope = NewScope(scope_, EVAL_SCOPE);
1278 scope->set_start_position(scope_->start_position());
1279 scope->set_end_position(scope_->end_position());
1280 scope_ = scope;
1281 if (eval_scope != NULL) {
1282 // Caller will correct the positions of the ad hoc eval scope.
1283 *eval_scope = scope;
1284 }
1285 mode_ = PARSE_EAGERLY;
1286 }
1287 scope_->SetLanguageMode(static_cast<LanguageMode>( 1265 scope_->SetLanguageMode(static_cast<LanguageMode>(
1288 scope_->language_mode() | STRICT_BIT)); 1266 scope_->language_mode() | STRICT_BIT));
1289 } 1267 }
1290 1268
1291 if (use_strong_found) { 1269 if (use_strong_found) {
1292 scope_->SetLanguageMode(static_cast<LanguageMode>( 1270 scope_->SetLanguageMode(static_cast<LanguageMode>(
1293 scope_->language_mode() | STRONG_BIT)); 1271 scope_->language_mode() | STRONG_BIT));
1294 } 1272 }
1273 // Because declarations in strict eval code don't leak into the scope
1274 // of the eval call, it is likely that functions declared in strict
1275 // eval code will be used within the eval code, so lazy parsing is
1276 // probably not a win. Also, resolution of "var" bindings defined in
1277 // strict eval code from within nested functions is currently broken
1278 // with the pre-parser; lazy parsing of strict eval code causes
1279 // regress/regress-crbug-135066.js to fail.
1280 if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY;
1295 } else if (literal->raw_value()->AsString() == 1281 } else if (literal->raw_value()->AsString() ==
1296 ast_value_factory()->use_asm_string() && 1282 ast_value_factory()->use_asm_string() &&
1297 token_loc.end_pos - token_loc.beg_pos == 1283 token_loc.end_pos - token_loc.beg_pos ==
1298 ast_value_factory()->use_asm_string()->length() + 2) { 1284 ast_value_factory()->use_asm_string()->length() + 2) {
1299 // Store the usage count; The actual use counter on the isolate is 1285 // Store the usage count; The actual use counter on the isolate is
1300 // incremented after parsing is done. 1286 // incremented after parsing is done.
1301 ++use_counts_[v8::Isolate::kUseAsm]; 1287 ++use_counts_[v8::Isolate::kUseAsm];
1302 scope_->SetAsmModule(); 1288 scope_->SetAsmModule();
1303 } 1289 }
1304 } else { 1290 } else {
(...skipping 2959 matching lines...) Expand 10 before | Expand all | Expand 10 after
4264 Assignment* assignment = factory()->NewAssignment( 4250 Assignment* assignment = factory()->NewAssignment(
4265 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); 4251 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
4266 VariableProxy* get_proxy = factory()->NewVariableProxy( 4252 VariableProxy* get_proxy = factory()->NewVariableProxy(
4267 function_state_->generator_object_variable()); 4253 function_state_->generator_object_variable());
4268 Yield* yield = factory()->NewYield( 4254 Yield* yield = factory()->NewYield(
4269 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); 4255 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
4270 body->Add(factory()->NewExpressionStatement( 4256 body->Add(factory()->NewExpressionStatement(
4271 yield, RelocInfo::kNoPosition), zone()); 4257 yield, RelocInfo::kNoPosition), zone());
4272 } 4258 }
4273 4259
4274 ParseStatementList(body, Token::RBRACE, false, NULL, CHECK_OK); 4260 ParseStatementList(body, Token::RBRACE, CHECK_OK);
4275 4261
4276 if (IsGeneratorFunction(kind)) { 4262 if (IsGeneratorFunction(kind)) {
4277 VariableProxy* get_proxy = factory()->NewVariableProxy( 4263 VariableProxy* get_proxy = factory()->NewVariableProxy(
4278 function_state_->generator_object_variable()); 4264 function_state_->generator_object_variable());
4279 Expression* undefined = 4265 Expression* undefined =
4280 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); 4266 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
4281 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, 4267 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
4282 RelocInfo::kNoPosition); 4268 RelocInfo::kNoPosition);
4283 body->Add(factory()->NewExpressionStatement( 4269 body->Add(factory()->NewExpressionStatement(
4284 yield, RelocInfo::kNoPosition), zone()); 4270 yield, RelocInfo::kNoPosition), zone());
(...skipping 1546 matching lines...) Expand 10 before | Expand all | Expand 10 after
5831 5817
5832 Expression* Parser::SpreadCallNew(Expression* function, 5818 Expression* Parser::SpreadCallNew(Expression* function,
5833 ZoneList<v8::internal::Expression*>* args, 5819 ZoneList<v8::internal::Expression*>* args,
5834 int pos) { 5820 int pos) {
5835 args->InsertAt(0, function, zone()); 5821 args->InsertAt(0, function, zone());
5836 5822
5837 return factory()->NewCallRuntime( 5823 return factory()->NewCallRuntime(
5838 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5824 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5839 } 5825 }
5840 } } // namespace v8::internal 5826 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/runtime/runtime-scopes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698