Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |