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

Issue 2316233004: Class fields, part 2 (desugaring) (Closed)
Patch Set: 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/parsing/parser.h ('k') | src/parsing/parser-base.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/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 if (compile_options_ == ScriptCompiler::kNoCompileOptions) { 143 if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
144 cached_parse_data_ = NULL; 144 cached_parse_data_ = NULL;
145 } else { 145 } else {
146 DCHECK(info->cached_data() != NULL); 146 DCHECK(info->cached_data() != NULL);
147 if (compile_options_ == ScriptCompiler::kConsumeParserCache) { 147 if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
148 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); 148 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
149 } 149 }
150 } 150 }
151 } 151 }
152 152
153 Expression* Parser::CallClassFieldInitializer(Scope* scope,
154 Expression* this_expr) {
Dan Ehrenberg 2016/09/09 22:54:42 For desugarings like this, even simple ones, could
bakkot 2016/09/12 19:10:11 Done.
155 const AstRawString* init_fn_name =
156 ast_value_factory()->GetOneByteString(".class-field-initializer");
157 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name);
158 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
159 args->Add(init_fn_proxy, zone());
160 args->Add(this_expr, zone());
161 return factory()->NewCallRuntime(Runtime::kInlineCall, args,
162 kNoSourcePosition);
163 }
164
165 Expression* Parser::RewriteSuperCall(Expression* super_call) {
Dan Ehrenberg 2016/09/09 22:54:41 Please add a comment showing what this desugars in
bakkot 2016/09/12 19:10:10 Done.
166 if (!allow_harmony_class_fields()) {
Dan Ehrenberg 2016/09/09 22:54:41 Ideally we should also take this path if the class
bakkot 2016/09/12 19:10:10 Unfortunately not. The super call might occur befo
167 return super_call;
168 }
169 // TODO(bakkot) The whole charade with the do expression can be replaced by a
170 // ternary conditional, except that the optimizer does not like it if you use
171 // an AST node (at least, one containing a variable proxy) in two places.
Dan Ehrenberg 2016/09/09 22:54:41 That's right, an AST node is single-use. You can s
bakkot 2016/09/12 19:10:11 At that point the if statement is more efficient a
172 Variable* var_tmp =
173 scope()->NewTemporary(ast_value_factory()->empty_string());
174 Block* block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
175 Assignment* assignment = factory()->NewAssignment(
176 Token::ASSIGN, factory()->NewVariableProxy(var_tmp), super_call,
177 kNoSourcePosition);
178 block->statements()->Add(
179 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
180 const AstRawString* init_fn_name =
181 ast_value_factory()->GetOneByteString(".class-field-initializer");
182 VariableProxy* init_fn_proxy =
183 scope()->NewUnresolved(factory(), init_fn_name);
184 Expression* condition = init_fn_proxy;
185 Statement* initialize = factory()->NewExpressionStatement(
186 CallClassFieldInitializer(scope(), factory()->NewVariableProxy(var_tmp)),
187 kNoSourcePosition);
188 IfStatement* if_statement = factory()->NewIfStatement(
189 condition, initialize, factory()->NewEmptyStatement(kNoSourcePosition),
190 kNoSourcePosition);
191 block->statements()->Add(if_statement, zone());
192 return factory()->NewDoExpression(block, var_tmp, kNoSourcePosition);
193 }
194
153 FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, 195 FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
154 bool call_super, 196 bool call_super,
155 bool requires_class_field_init, 197 bool requires_class_field_init,
156 int pos, int end_pos, 198 int pos, int end_pos,
157 LanguageMode language_mode) { 199 LanguageMode language_mode) {
158 int materialized_literal_count = -1; 200 int materialized_literal_count = -1;
159 int expected_property_count = -1; 201 int expected_property_count = -1;
160 int parameter_count = 0; 202 int parameter_count = 0;
161 if (name == nullptr) name = ast_value_factory()->empty_string(); 203 if (name == nullptr) name = ast_value_factory()->empty_string();
162 204
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 args->Add(super_constructor, zone()); 241 args->Add(super_constructor, zone());
200 Spread* spread_args = factory()->NewSpread( 242 Spread* spread_args = factory()->NewSpread(
201 factory()->NewVariableProxy(constructor_args), pos, pos); 243 factory()->NewVariableProxy(constructor_args), pos, pos);
202 ZoneList<Expression*>* spread_args_expr = 244 ZoneList<Expression*>* spread_args_expr =
203 new (zone()) ZoneList<Expression*>(1, zone()); 245 new (zone()) ZoneList<Expression*>(1, zone());
204 spread_args_expr->Add(spread_args, zone()); 246 spread_args_expr->Add(spread_args, zone());
205 args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone()); 247 args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone());
206 VariableProxy* new_target_proxy = 248 VariableProxy* new_target_proxy =
207 NewUnresolved(ast_value_factory()->new_target_string(), pos); 249 NewUnresolved(ast_value_factory()->new_target_string(), pos);
208 args->Add(new_target_proxy, zone()); 250 args->Add(new_target_proxy, zone());
209 CallRuntime* call = factory()->NewCallRuntime( 251 Expression* call = factory()->NewCallRuntime(
210 Context::REFLECT_CONSTRUCT_INDEX, args, pos); 252 Context::REFLECT_CONSTRUCT_INDEX, args, pos);
253 if (requires_class_field_init) {
254 call = CallClassFieldInitializer(scope(), call);
255 }
211 body->Add(factory()->NewReturnStatement(call, pos), zone()); 256 body->Add(factory()->NewReturnStatement(call, pos), zone());
212 } 257 }
213 258
214 materialized_literal_count = function_state.materialized_literal_count(); 259 materialized_literal_count = function_state.materialized_literal_count();
215 expected_property_count = function_state.expected_property_count(); 260 expected_property_count = function_state.expected_property_count();
216 } 261 }
217 262
218 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( 263 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
219 name, function_scope, body, materialized_literal_count, 264 name, function_scope, body, materialized_literal_count,
220 expected_property_count, parameter_count, 265 expected_property_count, parameter_count,
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 // must produce a FunctionLiteral. 949 // must produce a FunctionLiteral.
905 DCHECK(expression->IsFunctionLiteral()); 950 DCHECK(expression->IsFunctionLiteral());
906 result = expression->AsFunctionLiteral(); 951 result = expression->AsFunctionLiteral();
907 } else { 952 } else {
908 ok = false; 953 ok = false;
909 } 954 }
910 } 955 }
911 } 956 }
912 } else if (info->is_default_constructor()) { 957 } else if (info->is_default_constructor()) {
913 DCHECK_EQ(scope(), outer); 958 DCHECK_EQ(scope(), outer);
959 bool is_subclass_constructor =
960 IsSubclassConstructor(info->function_kind());
914 result = DefaultConstructor( 961 result = DefaultConstructor(
915 raw_name, IsSubclassConstructor(info->function_kind()), 962 raw_name, is_subclass_constructor, info->requires_class_field_init(),
916 info->requires_class_field_init(), info->start_position(), 963 info->start_position(), info->end_position(), info->language_mode());
917 info->end_position(), info->language_mode()); 964 if (!is_subclass_constructor && info->requires_class_field_init()) {
965 result = InsertClassFieldInitializer(result);
966 }
967 } else if (info->is_class_field_initializer()) {
968 Handle<SharedFunctionInfo> shared_info = info->shared_info();
969 DCHECK(!shared_info.is_null());
970 if (shared_info->length() == 0) {
971 result = ParseClassFieldForInitializer(
972 info->start_position() != info->end_position(), &ok);
973 } else {
974 result = SynthesizeClassFieldInitializer(shared_info->length());
975 }
918 } else { 976 } else {
919 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), 977 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
920 kSkipFunctionNameCheck, 978 kSkipFunctionNameCheck,
921 info->function_kind(), kNoSourcePosition, 979 info->function_kind(), kNoSourcePosition,
922 function_type, info->language_mode(), &ok); 980 function_type, info->language_mode(), &ok);
981 if (info->requires_class_field_init()) {
982 result = InsertClassFieldInitializer(result);
983 }
923 } 984 }
924 // Make sure the results agree. 985 // Make sure the results agree.
925 DCHECK(ok == (result != nullptr)); 986 DCHECK(ok == (result != nullptr));
926 } 987 }
927 988
928 // Make sure the target stack is empty. 989 // Make sure the target stack is empty.
929 DCHECK_NULL(target_stack_); 990 DCHECK_NULL(target_stack_);
930 return result; 991 return result;
931 } 992 }
932 993
(...skipping 3255 matching lines...) Expand 10 before | Expand all | Expand 10 after
4188 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 4249 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4189 language_mode(), function_state_->kind(), 4250 language_mode(), function_state_->kind(),
4190 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, 4251 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_,
4191 logger, may_abort, use_counts_); 4252 logger, may_abort, use_counts_);
4192 if (pre_parse_timer_ != NULL) { 4253 if (pre_parse_timer_ != NULL) {
4193 pre_parse_timer_->Stop(); 4254 pre_parse_timer_->Stop();
4194 } 4255 }
4195 return result; 4256 return result;
4196 } 4257 }
4197 4258
4259 Expression* Parser::InstallHomeObject(Expression* function_literal,
4260 Expression* home_object) {
4261 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
4262 Variable* result_var =
4263 scope()->NewTemporary(ast_value_factory()->empty_string());
4264 DoExpression* do_expr =
4265 factory()->NewDoExpression(do_block, result_var, kNoSourcePosition);
4266 Assignment* init = factory()->NewAssignment(
4267 Token::ASSIGN, factory()->NewVariableProxy(result_var), function_literal,
4268 kNoSourcePosition);
4269 do_block->statements()->Add(
4270 factory()->NewExpressionStatement(init, kNoSourcePosition), zone());
4271 Property* home_object_property = factory()->NewProperty(
4272 factory()->NewVariableProxy(result_var),
4273 factory()->NewSymbolLiteral("home_object_symbol", kNoSourcePosition),
4274 kNoSourcePosition);
4275 Assignment* assignment = factory()->NewAssignment(
4276 Token::ASSIGN, home_object_property, home_object, kNoSourcePosition);
4277 do_block->statements()->Add(
4278 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
4279 return do_expr;
4280 }
4281
4282 const AstRawString* ClassFieldVariableName(bool is_name,
4283 AstValueFactory* ast_value_factory,
4284 int index) {
4285 std::string name =
4286 ".class-field-" + std::to_string(index) + (is_name ? "-name" : "-func");
Dan Ehrenberg 2016/09/09 22:54:41 Eh, I guess this works, and it's clean code, but t
bakkot 2016/09/12 19:10:10 No, the return value of this function is used by N
4287 return ast_value_factory->GetOneByteString(name.c_str());
4288 }
4289
4290 FunctionLiteral* Parser::SynthesizeClassFieldInitializer(int count) {
Dan Ehrenberg 2016/09/09 22:54:42 Add a comment showing what this desugars into
bakkot 2016/09/12 19:10:10 Done.
4291 DCHECK(count > 0);
4292 // Makes a function which reads the names and initializers for each class
4293 // field out of deterministically named local variables and sets each property
4294 // to the result of evaluating its corresponding initializer in turn.
4295 RaiseLanguageMode(STRICT);
4296 FunctionKind kind = FunctionKind::kConciseMethod;
4297 DeclarationScope* initializer_scope = NewFunctionScope(kind);
4298 SetLanguageMode(initializer_scope, language_mode());
4299 initializer_scope->set_start_position(scanner()->location().end_pos);
4300 initializer_scope->set_end_position(scanner()->location().end_pos);
4301 FunctionState initializer_state(&function_state_, &scope_state_,
4302 initializer_scope, kind);
4303 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(count, zone());
4304 for (int i = 0; i < count; ++i) {
4305 const AstRawString* name =
4306 ClassFieldVariableName(true, ast_value_factory(), i);
4307 VariableProxy* name_proxy = scope()->NewUnresolved(factory(), name);
4308 const AstRawString* function_name =
4309 ClassFieldVariableName(false, ast_value_factory(), i);
4310 VariableProxy* function_proxy =
4311 scope()->NewUnresolved(factory(), function_name);
4312 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4313 args->Add(function_proxy, zone());
4314 args->Add(ThisExpression(kNoSourcePosition), zone());
4315 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args,
4316 kNoSourcePosition);
4317 ZoneList<Expression*>* define_property_args =
4318 new (zone()) ZoneList<Expression*>(5, zone());
4319 define_property_args->Add(ThisExpression(kNoSourcePosition), zone());
4320 define_property_args->Add(name_proxy, zone());
4321 define_property_args->Add(call, zone());
4322 define_property_args->Add(
4323 factory()->NewNumberLiteral(DONT_ENUM, kNoSourcePosition), zone());
4324 define_property_args->Add(
4325 factory()->NewNumberLiteral(
4326 false, // TODO(bakkot) function name inference a la class { x =
4327 // function(){}; static y = function(){}; }
Dan Ehrenberg 2016/09/09 22:54:41 Function name inference sounds like a ship blocker
bakkot 2016/09/12 19:10:10 Nope: https://github.com/tc39/proposal-class-publi
4328 kNoSourcePosition),
4329 zone());
4330 body->Add(factory()->NewExpressionStatement(
4331 factory()->NewCallRuntime(
4332 Runtime::kDefineDataPropertyInLiteral,
4333 define_property_args, // TODO(bakkot) verify that this is
4334 // the same as object_define_property
4335 kNoSourcePosition),
4336 kNoSourcePosition),
4337 zone());
4338 }
4339 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition),
4340 kNoSourcePosition),
4341 zone());
4342 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
4343 ast_value_factory()->empty_string(), initializer_scope, body,
4344 initializer_state.materialized_literal_count(),
4345 initializer_state.expected_property_count(), 0,
4346 FunctionLiteral::kNoDuplicateParameters,
4347 FunctionLiteral::kAnonymousExpression,
4348 FunctionLiteral::kShouldLazyCompile, kind,
4349 initializer_scope->start_position());
4350 function_literal->set_is_class_field_initializer(true);
4351 function_literal->scope()->set_default_function_length(count);
4352 return function_literal;
4353 }
4354
4355 FunctionLiteral* Parser::InsertClassFieldInitializer(
4356 FunctionLiteral* constructor) {
4357 Statement* call_initializer = factory()->NewExpressionStatement(
4358 CallClassFieldInitializer(
4359 constructor->scope(),
4360 constructor->scope()->NewUnresolved(
4361 factory(), ast_value_factory()->this_string(), kNoSourcePosition,
4362 kNoSourcePosition + 4, Variable::THIS)),
4363 kNoSourcePosition);
4364 constructor->body()->InsertAt(0, call_initializer, zone());
4365 return constructor;
4366 }
4367
4198 Expression* Parser::ParseClassLiteral(const AstRawString* name, 4368 Expression* Parser::ParseClassLiteral(const AstRawString* name,
4199 Scanner::Location class_name_location, 4369 Scanner::Location class_name_location,
4200 bool name_is_strict_reserved, int pos, 4370 bool name_is_strict_reserved, int pos,
4201 bool* ok) { 4371 bool* ok) {
4202 // All parts of a ClassDeclaration and ClassExpression are strict code. 4372 // All parts of a ClassDeclaration and ClassExpression are strict code.
4203 if (name_is_strict_reserved) { 4373 if (name_is_strict_reserved) {
4204 ReportMessageAt(class_name_location, 4374 ReportMessageAt(class_name_location,
4205 MessageTemplate::kUnexpectedStrictReserved); 4375 MessageTemplate::kUnexpectedStrictReserved);
4206 *ok = false; 4376 *ok = false;
4207 return nullptr; 4377 return nullptr;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4269 impl()->AccumulateFormalParameterContainmentErrors(); 4439 impl()->AccumulateFormalParameterContainmentErrors();
4270 4440
4271 if (has_seen_constructor && constructor == nullptr) { 4441 if (has_seen_constructor && constructor == nullptr) {
4272 constructor = GetPropertyValue(property)->AsFunctionLiteral(); 4442 constructor = GetPropertyValue(property)->AsFunctionLiteral();
4273 DCHECK_NOT_NULL(constructor); 4443 DCHECK_NOT_NULL(constructor);
4274 constructor->set_raw_name( 4444 constructor->set_raw_name(
4275 name != nullptr ? name : ast_value_factory()->empty_string()); 4445 name != nullptr ? name : ast_value_factory()->empty_string());
4276 } else { 4446 } else {
4277 if (property->kind() == ClassLiteralProperty::FIELD) { 4447 if (property->kind() == ClassLiteralProperty::FIELD) {
4278 DCHECK(allow_harmony_class_fields()); 4448 DCHECK(allow_harmony_class_fields());
4279 continue; // TODO(bakkot) implementation 4449 if (property->is_static()) {
4450 if (static_initializer_var == nullptr) {
4451 static_initializer_var =
4452 NewTemporary(ast_value_factory()->empty_string());
4453 }
4454 // TODO(bakkot) only do this conditionally
4455 Expression* function = InstallHomeObject(
4456 property->value(),
4457 factory()->NewVariableProxy(static_initializer_var));
4458 ZoneList<Expression*>* args =
4459 new (zone()) ZoneList<Expression*>(2, zone());
4460 args->Add(function, zone());
4461 args->Add(factory()->NewVariableProxy(static_initializer_var),
4462 zone());
4463 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall,
4464 args, kNoSourcePosition);
4465 property->set_value(call);
4466 } else {
4467 // if (is_computed_name) { // TODO(bakkot) figure out why this is
4468 // necessary for non-computed names in full-codegen
Dan Ehrenberg 2016/09/09 22:54:41 What happens when you don't include this on a non-
bakkot 2016/09/12 19:10:10 That argument fails an IsName check in DefineDataP
4469 ZoneList<Expression*>* to_name_args =
4470 new (zone()) ZoneList<Expression*>(1, zone());
4471 to_name_args->Add(property->key(), zone());
4472 property->set_key(factory()->NewCallRuntime(
4473 Runtime::kToName, to_name_args, kNoSourcePosition));
4474 //}
4475 const AstRawString* name = ClassFieldVariableName(
4476 true, ast_value_factory(), instance_field_initializers->length());
4477 VariableProxy* name_proxy = NewUnresolved(name);
4478 Declaration* name_declaration =
4479 factory()
4480 ->NewVariableDeclaration( // TODO(bakkot) DeclareLocal? not
4481 // clear on the difference...
Dan Ehrenberg 2016/09/09 22:54:42 Generally in the parser, you can either use a NewV
4482 name_proxy, scope(), kNoSourcePosition);
4483 Variable* name_var =
4484 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
4485 kNeedsInitialization, ok, scope());
4486 DCHECK(ok);
4487 if (!ok) return nullptr;
4488 instance_field_initializers->Add(property->value(), zone());
4489 property->set_value(factory()->NewVariableProxy(name_var));
4490 }
4280 } 4491 }
4281 properties->Add(property, zone()); 4492 properties->Add(property, zone());
4282 } 4493 }
4283 4494
4284 DCHECK_NOT_NULL(fni_); 4495 DCHECK_NOT_NULL(fni_);
4285 fni_->Infer(); 4496 fni_->Infer();
4286 } 4497 }
4287 4498
4288 Expect(Token::RBRACE, CHECK_OK); 4499 Expect(Token::RBRACE, CHECK_OK);
4289 int end_pos = scanner()->location().end_pos; 4500 int end_pos = scanner()->location().end_pos;
4290 4501
4291 bool has_instance_fields = instance_field_initializers->length() > 0; 4502 bool has_instance_fields = instance_field_initializers->length() > 0;
4292 DCHECK(!has_instance_fields || allow_harmony_class_fields()); 4503 DCHECK(!has_instance_fields || allow_harmony_class_fields());
4293 bool has_default_constructor = constructor == nullptr; 4504 bool has_default_constructor = constructor == nullptr;
4294 if (has_default_constructor) { 4505 if (has_default_constructor) {
4295 constructor = DefaultConstructor(name, has_extends, has_instance_fields, 4506 constructor = DefaultConstructor(name, has_extends, has_instance_fields,
4296 pos, end_pos, block_state.language_mode()); 4507 pos, end_pos, block_state.language_mode());
4297 } 4508 }
4298 4509
4299 if (has_instance_fields && extends == nullptr) { 4510 if (has_instance_fields && extends == nullptr) {
4511 constructor = InsertClassFieldInitializer(constructor);
4300 constructor->set_requires_class_field_init(true); 4512 constructor->set_requires_class_field_init(true);
4301 } // The derived case is handled by rewriting super calls. 4513 } // The derived case is handled by rewriting super calls.
4302 4514
4303 block_state.set_end_position(end_pos); 4515 block_state.set_end_position(end_pos);
4304 4516
4305 if (name != nullptr) { 4517 if (name != nullptr) {
4306 DCHECK_NOT_NULL(proxy); 4518 DCHECK_NOT_NULL(proxy);
4307 proxy->var()->set_initializer_position(end_pos); 4519 proxy->var()->set_initializer_position(end_pos);
4308 } 4520 }
4309 4521
4310 ClassLiteral* class_literal = factory()->NewClassLiteral( 4522 ClassLiteral* class_literal = factory()->NewClassLiteral(
4311 proxy, extends, constructor, properties, pos, end_pos); 4523 proxy, extends, constructor, properties, pos, end_pos);
4312 4524
4313 if (static_initializer_var != nullptr) { 4525 if (static_initializer_var != nullptr) {
4314 class_literal->set_static_initializer_proxy( 4526 class_literal->set_static_initializer_proxy(
4315 factory()->NewVariableProxy(static_initializer_var)); 4527 factory()->NewVariableProxy(static_initializer_var));
4316 } 4528 }
4317 4529
4318 do_block->statements()->Add( 4530 do_block->statements()->Add(
4319 factory()->NewExpressionStatement( 4531 factory()->NewExpressionStatement(
4320 factory()->NewAssignment(Token::ASSIGN, 4532 factory()->NewAssignment(Token::ASSIGN,
4321 factory()->NewVariableProxy(result_var), 4533 factory()->NewVariableProxy(result_var),
4322 class_literal, kNoSourcePosition), 4534 class_literal, kNoSourcePosition),
4323 pos), 4535 pos),
4324 zone()); 4536 zone());
4537 if (allow_harmony_class_fields() &&
4538 (has_instance_fields ||
4539 (extends != nullptr && !has_default_constructor))) {
4540 // Default constructors for derived classes without fields will not try to
4541 // read this variable, so there's no need to create it.
4542 const AstRawString* init_fn_name =
4543 ast_value_factory()->GetOneByteString(".class-field-initializer");
Dan Ehrenberg 2016/09/09 22:54:42 Put in src/heap-symbols.h
bakkot 2016/09/12 19:10:11 Done.
4544 Variable* init_fn_var =
4545 scope()->DeclareLocal(init_fn_name, CONST, kCreatedInitialized,
4546 Variable::NORMAL); // TODO(bakkot) flags
Dan Ehrenberg 2016/09/09 22:54:42 What flags do you think might be wrong here? This
bakkot 2016/09/12 19:10:10 Mostly I wasn't sure if kCreatedInitialized was co
4547 Expression* initializer =
4548 has_instance_fields
4549 ? static_cast<Expression*>(SynthesizeClassFieldInitializer(
4550 instance_field_initializers->length()))
4551 : factory()->NewBooleanLiteral(false, kNoSourcePosition);
4552 Assignment* assignment = factory()->NewAssignment(
4553 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer,
4554 kNoSourcePosition);
4555 do_block->statements()->Add(
4556 factory()->NewExpressionStatement(assignment, kNoSourcePosition),
4557 zone());
4558 }
4559 for (int i = 0; i < instance_field_initializers->length(); ++i) {
4560 const AstRawString* function_name =
4561 ClassFieldVariableName(false, ast_value_factory(), i);
4562 VariableProxy* function_proxy = NewUnresolved(function_name);
4563 Declaration* function_declaration = factory()->NewVariableDeclaration(
4564 function_proxy, scope(), kNoSourcePosition);
4565 Variable* function_var =
4566 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST,
4567 kNeedsInitialization, ok,
4568 scope()); // TODO(bakkot) declare vs declarelocal
Dan Ehrenberg 2016/09/09 22:54:42 Declare.
bakkot 2016/09/12 19:10:11 Thanks.
4569 DCHECK(ok);
4570 if (!ok) return nullptr;
4571 Property* prototype_property = factory()->NewProperty(
4572 factory()->NewVariableProxy(result_var),
4573 factory()->NewStringLiteral(ast_value_factory()->prototype_string(),
4574 kNoSourcePosition),
4575 kNoSourcePosition);
4576 Expression* function_value = InstallHomeObject(
4577 instance_field_initializers->at(i),
4578 prototype_property); // TODO(bakkot) ideally this would be conditional,
4579 // especially in trivial cases
Dan Ehrenberg 2016/09/09 22:54:42 As we discussed off-line, you can use the scope in
bakkot 2016/09/12 19:10:10 I'm going to make that change in a later patch, si
4580 Assignment* function_assignment = factory()->NewAssignment(
4581 Token::INIT, factory()->NewVariableProxy(function_var), function_value,
4582 kNoSourcePosition);
4583 do_block->statements()->Add(factory()->NewExpressionStatement(
4584 function_assignment, kNoSourcePosition),
4585 zone());
4586 }
4325 do_block->set_scope(block_state.FinalizedBlockScope()); 4587 do_block->set_scope(block_state.FinalizedBlockScope());
4326 do_expr->set_represented_function(constructor); 4588 do_expr->set_represented_function(constructor);
4327 4589
4328 return do_expr; 4590 return do_expr;
4329 } 4591 }
4330 4592
4331 4593
4332 Expression* Parser::ParseV8Intrinsic(bool* ok) { 4594 Expression* Parser::ParseV8Intrinsic(bool* ok) {
4333 // CallRuntime :: 4595 // CallRuntime ::
4334 // '%' Identifier Arguments 4596 // '%' Identifier Arguments
(...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after
6208 node->Print(Isolate::Current()); 6470 node->Print(Isolate::Current());
6209 } 6471 }
6210 #endif // DEBUG 6472 #endif // DEBUG
6211 6473
6212 #undef CHECK_OK 6474 #undef CHECK_OK
6213 #undef CHECK_OK_VOID 6475 #undef CHECK_OK_VOID
6214 #undef CHECK_FAILED 6476 #undef CHECK_FAILED
6215 6477
6216 } // namespace internal 6478 } // namespace internal
6217 } // namespace v8 6479 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698