Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index 26f2ad7adb095eb5f22a4e1473c56684e15d4ad5..51cf5e2e3594013f410b1bd442da19ca7367977f 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -1007,14 +1007,18 @@ void Parser::ParseFunction(ParsedFunction* parsed_function) { |
| } |
| -RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) { |
| +RawObject* Parser::ParseMetadata(const Field& meta_data) { |
| Thread* thread = Thread::Current(); |
| Isolate* isolate = thread->isolate(); |
| StackZone stack_zone(thread); |
| Zone* zone = stack_zone.GetZone(); |
| LongJumpScope jump; |
| + |
| + const Class& owner_class = Class::Handle(zone, meta_data.owner()); |
| + const Script& script = Script::Handle(zone, meta_data.script()); |
| + const intptr_t token_pos = meta_data.token_pos(); |
| + |
| if (setjmp(*jump.Set()) == 0) { |
| - const Script& script = Script::Handle(zone, cls.script()); |
| // Parsing metadata can involve following paths in the parser that are |
| // normally used for expressions and assume current_function is non-null, |
| // so we create a fake function to use as the current_function rather than |
| @@ -1027,13 +1031,13 @@ RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) { |
| false, // is_abstract |
| false, // is_external |
| false, // is_native |
| - cls, |
| + Object::Handle(zone, meta_data.RawOwner()), |
| token_pos)); |
| fake_function.set_is_debuggable(false); |
| ParsedFunction* parsed_function = |
| new ParsedFunction(thread, fake_function); |
| Parser parser(script, parsed_function, token_pos); |
| - parser.set_current_class(cls); |
| + parser.set_current_class(owner_class); |
| RawObject* metadata = parser.EvaluateMetadata(); |
| return metadata; |
| @@ -1145,18 +1149,14 @@ ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) { |
| // TODO(koda): Should there be a StackZone here? |
| Zone* zone = thread->zone(); |
| - const Class& script_cls = Class::Handle(zone, field.origin()); |
| - const Script& script = Script::Handle(zone, script_cls.script()); |
| - |
| const String& field_name = String::Handle(zone, field.name()); |
| String& init_name = String::Handle(zone, |
| Symbols::FromConcat(Symbols::InitPrefix(), field_name)); |
| + const Script& script = Script::Handle(zone, field.script()); |
| Object& initializer_owner = Object::Handle(field.owner()); |
| - if (field.owner() != field.origin()) { |
| - initializer_owner = |
| - PatchClass::New(Class::Handle(field.owner()), script_cls); |
| - } |
| + initializer_owner = |
| + PatchClass::New(Class::Handle(field.owner()), script); |
| const Function& initializer = Function::ZoneHandle(zone, |
| Function::New(init_name, |
| @@ -1847,6 +1847,13 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value, |
| const bool no_explicit_default_values = false; |
| ParseFormalParameterList(no_explicit_default_values, false, &func_params); |
| + // In top-level and mixin functions, the source may be in a different |
| + // script than the script of the current class. |
| + Object& sig_func_owner = Object::Handle(Z, current_class().raw()); |
| + if (current_class().script() != script_.raw()) { |
| + sig_func_owner = PatchClass::New(current_class(), script_); |
|
Ivan Posva
2015/11/30 23:54:26
If the current_class().script and script_.raw() ar
hausner
2015/12/01 19:38:17
Yes. But unless I add the RawOwner to the Parser c
|
| + } |
| + |
| // The field 'is_static' has no meaning for signature functions. |
| const Function& signature_function = Function::Handle(Z, |
| Function::New(*parameter.name, |
| @@ -1856,18 +1863,18 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value, |
| /* is_abstract = */ false, |
| /* is_external = */ false, |
| /* is_native = */ false, |
| - current_class(), |
| + sig_func_owner, |
| parameter.name_pos)); |
| signature_function.set_result_type(result_type); |
| signature_function.set_is_debuggable(false); |
| AddFormalParamsToFunction(&func_params, signature_function); |
| - const String& signature = String::Handle(Z, |
| - signature_function.Signature()); |
| + const String& signature = |
| + String::Handle(Z, signature_function.Signature()); |
| // Lookup the signature class, i.e. the class whose name is the signature. |
| // We only lookup in the current library, but not in its imports, and only |
| // create a new canonical signature class if it does not exist yet. |
| - Class& signature_class = Class::ZoneHandle(Z, |
| - library_.LookupLocalClass(signature)); |
| + Class& signature_class = |
| + Class::ZoneHandle(Z, library_.LookupLocalClass(signature)); |
| if (signature_class.IsNull()) { |
| signature_class = Class::NewSignatureClass(signature, |
| signature_function, |
| @@ -4414,7 +4421,7 @@ void Parser::ParseClassMemberDefinition(ClassDesc* members, |
| void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes, |
| - const Class& toplevel_class, |
| + const PatchClass& tl_owner, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseEnumDeclaration"); |
| const intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos |
| @@ -4456,7 +4463,7 @@ void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes, |
| cls.set_is_synthesized_class(); |
| cls.set_is_enum_class(); |
| if (metadata_pos >= 0) { |
| - library_.AddClassMetadata(cls, toplevel_class, metadata_pos); |
| + library_.AddClassMetadata(cls, tl_owner, metadata_pos); |
| } |
| cls.set_super_type(Type::Handle(Z, Type::ObjectType())); |
| pending_classes.Add(cls, Heap::kOld); |
| @@ -4464,7 +4471,7 @@ void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes, |
| void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, |
| - const Class& toplevel_class, |
| + const PatchClass& tl_owner, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseClassDeclaration"); |
| bool is_patch = false; |
| @@ -4579,7 +4586,7 @@ void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, |
| cls.set_is_abstract(); |
| } |
| if (metadata_pos >= 0) { |
| - library_.AddClassMetadata(cls, toplevel_class, metadata_pos); |
| + library_.AddClassMetadata(cls, tl_owner, metadata_pos); |
| } |
| const bool is_mixin_declaration = (CurrentToken() == Token::kASSIGN); |
| @@ -4959,7 +4966,7 @@ void Parser::CheckConstructors(ClassDesc* class_desc) { |
| void Parser::ParseMixinAppAlias( |
| const GrowableObjectArray& pending_classes, |
| - const Class& toplevel_class, |
| + const PatchClass& tl_owner, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseMixinAppAlias"); |
| const intptr_t classname_pos = TokenPos(); |
| @@ -5013,7 +5020,7 @@ void Parser::ParseMixinAppAlias( |
| ExpectSemicolon(); |
| pending_classes.Add(mixin_application, Heap::kOld); |
| if (metadata_pos >= 0) { |
| - library_.AddClassMetadata(mixin_application, toplevel_class, metadata_pos); |
| + library_.AddClassMetadata(mixin_application, tl_owner, metadata_pos); |
| } |
| } |
| @@ -5059,7 +5066,7 @@ bool Parser::IsMixinAppAlias() { |
| void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, |
| - const Class& toplevel_class, |
| + const PatchClass& tl_owner, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTypedef"); |
| intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos : TokenPos(); |
| @@ -5069,7 +5076,7 @@ void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, |
| if (FLAG_warn_mixin_typedef) { |
| ReportWarning(TokenPos(), "deprecated mixin application typedef"); |
| } |
| - ParseMixinAppAlias(pending_classes, toplevel_class, metadata_pos); |
| + ParseMixinAppAlias(pending_classes, tl_owner, metadata_pos); |
| return; |
| } |
| @@ -5180,7 +5187,7 @@ void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, |
| pending_classes.Add(function_type_alias, Heap::kOld); |
| if (metadata_pos >= 0) { |
| library_.AddClassMetadata(function_type_alias, |
| - toplevel_class, |
| + tl_owner, |
| metadata_pos); |
| } |
| } |
| @@ -5417,6 +5424,7 @@ RawAbstractType* Parser::ParseMixins(const AbstractType& super_type) { |
| void Parser::ParseTopLevelVariable(TopLevel* top_level, |
| + const PatchClass& owner, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelVariable"); |
| const bool is_const = (CurrentToken() == Token::kCONST); |
| @@ -5452,8 +5460,10 @@ void Parser::ParseTopLevelVariable(TopLevel* top_level, |
| const bool is_reflectable = |
| !(library_.is_dart_scheme() && library_.IsPrivate(var_name)); |
| - field = Field::New(var_name, is_static, is_final, is_const, is_reflectable, |
| - current_class(), type, name_pos); |
| + |
| + field = Field::NewTopLevel(var_name, is_final, is_const, owner, name_pos); |
| + field.SetFieldType(type); |
| + field.set_is_reflectable(is_reflectable); |
| field.SetStaticValue(Object::null_instance(), true); |
| top_level->AddField(field); |
| library_.AddObject(field, var_name); |
| @@ -5481,13 +5491,11 @@ void Parser::ParseTopLevelVariable(TopLevel* top_level, |
| /* is_abstract = */ false, |
| /* is_external = */ false, |
| /* is_native = */ false, |
| - current_class(), |
| + owner, |
| name_pos); |
| getter.set_result_type(type); |
| getter.set_is_debuggable(false); |
| - if (library_.is_dart_scheme() && library_.IsPrivate(var_name)) { |
| - getter.set_is_reflectable(false); |
| - } |
| + getter.set_is_reflectable(is_reflectable); |
| top_level->AddFunction(getter); |
| } |
| } else if (is_final) { |
| @@ -5534,6 +5542,7 @@ RawFunction::AsyncModifier Parser::ParseFunctionModifier() { |
| void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| + const PatchClass& owner, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelFunction"); |
| const intptr_t decl_begin_pos = TokenPos(); |
| @@ -5625,7 +5634,7 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| /* is_abstract = */ false, |
| is_external, |
| is_native, |
| - current_class(), |
| + owner, |
| decl_begin_pos)); |
| func.set_result_type(result_type); |
| func.set_end_token_pos(function_end_pos); |
| @@ -5641,6 +5650,12 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| if (!is_patch) { |
| library_.AddObject(func, func_name); |
| } else { |
| + // Need to remove the previously added function that is being patched. |
| + const Class& toplevel_cls = Class::Handle(Z, library_.toplevel_class()); |
| + const Function& replaced_func = |
| + Function::Handle(Z, toplevel_cls.LookupStaticFunction(func_name)); |
| + ASSERT(!replaced_func.IsNull()); |
| + toplevel_cls.RemoveFunction(replaced_func); |
| library_.ReplaceObject(func, func_name); |
| } |
| if (metadata_pos >= 0) { |
| @@ -5650,6 +5665,7 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| void Parser::ParseTopLevelAccessor(TopLevel* top_level, |
| + const PatchClass& owner, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelAccessor"); |
| const intptr_t decl_begin_pos = TokenPos(); |
| @@ -5780,7 +5796,7 @@ void Parser::ParseTopLevelAccessor(TopLevel* top_level, |
| /* is_abstract = */ false, |
| is_external, |
| is_native, |
| - current_class(), |
| + owner, |
| decl_begin_pos)); |
| func.set_result_type(result_type); |
| func.set_end_token_pos(accessor_end_pos); |
| @@ -5797,6 +5813,12 @@ void Parser::ParseTopLevelAccessor(TopLevel* top_level, |
| if (!is_patch) { |
| library_.AddObject(func, accessor_name); |
| } else { |
| + // Need to remove the previously added accessor that is being patched. |
| + const Class& toplevel_cls = Class::Handle(Z, owner.patched_class()); |
| + const Function& replaced_func = |
| + Function::Handle(Z, toplevel_cls.LookupFunction(accessor_name)); |
| + ASSERT(!replaced_func.IsNull()); |
| + toplevel_cls.RemoveFunction(replaced_func); |
| library_.ReplaceObject(func, accessor_name); |
| } |
| if (metadata_pos >= 0) { |
| @@ -5876,7 +5898,8 @@ void Parser::ParseIdentList(GrowableObjectArray* names) { |
| } |
| -void Parser::ParseLibraryImportExport(intptr_t metadata_pos) { |
| +void Parser::ParseLibraryImportExport(const PatchClass& tl_owner, |
| + intptr_t metadata_pos) { |
| bool is_import = (CurrentToken() == Token::kIMPORT); |
| bool is_export = (CurrentToken() == Token::kEXPORT); |
| ASSERT(is_import || is_export); |
| @@ -5961,7 +5984,7 @@ void Parser::ParseLibraryImportExport(intptr_t metadata_pos) { |
| Namespace& ns = Namespace::Handle(Z, |
| Namespace::New(library, show_names, hide_names)); |
| if (metadata_pos >= 0) { |
| - ns.AddMetadata(metadata_pos, current_class()); |
| + ns.AddMetadata(tl_owner, metadata_pos); |
| } |
| // Ensure that private dart:_ libraries are only imported into dart: |
| @@ -6024,7 +6047,7 @@ void Parser::ParseLibraryPart() { |
| } |
| -void Parser::ParseLibraryDefinition() { |
| +void Parser::ParseLibraryDefinition(const PatchClass& tl_owner) { |
| TRACE_PARSER("ParseLibraryDefinition"); |
| // Handle the script tag. |
| @@ -6047,14 +6070,14 @@ void Parser::ParseLibraryDefinition() { |
| } |
| ParseLibraryName(); |
| if (metadata_pos >= 0) { |
| - library_.AddLibraryMetadata(current_class(), metadata_pos); |
| + library_.AddLibraryMetadata(tl_owner, metadata_pos); |
| } |
| rewind_pos = TokenPos(); |
| metadata_pos = SkipMetadata(); |
| } |
| while ((CurrentToken() == Token::kIMPORT) || |
| (CurrentToken() == Token::kEXPORT)) { |
| - ParseLibraryImportExport(metadata_pos); |
| + ParseLibraryImportExport(tl_owner, metadata_pos); |
| rewind_pos = TokenPos(); |
| metadata_pos = SkipMetadata(); |
| } |
| @@ -6106,13 +6129,20 @@ void Parser::ParseTopLevel() { |
| SetPosition(0); |
| is_top_level_ = true; |
| TopLevel top_level(Z); |
| - Class& toplevel_class = Class::Handle(Z, |
| - Class::New(Symbols::TopLevel(), script_, TokenPos())); |
| - toplevel_class.set_library(library_); |
| + |
| + Class& toplevel_class = Class::Handle(Z, library_.toplevel_class()); |
| + if (toplevel_class.IsNull()) { |
| + toplevel_class = Class::New(Symbols::TopLevel(), script_, TokenPos()); |
| + toplevel_class.set_library(library_); |
| + library_.set_toplevel_class(toplevel_class); |
|
Ivan Posva
2015/11/30 23:54:27
For this compilation unit we can use this top leve
hausner
2015/12/01 19:38:17
Done.
|
| + } |
| + |
| + const PatchClass& tl_owner = |
| + PatchClass::ZoneHandle(PatchClass::New(toplevel_class, script_)); |
| if (is_library_source() || is_patch_source()) { |
| set_current_class(toplevel_class); |
| - ParseLibraryDefinition(); |
| + ParseLibraryDefinition(tl_owner); |
| } else if (is_part_source()) { |
| ParsePartHeader(); |
| } |
| @@ -6122,27 +6152,27 @@ void Parser::ParseTopLevel() { |
| set_current_class(cls); // No current class. |
| intptr_t metadata_pos = SkipMetadata(); |
| if (CurrentToken() == Token::kCLASS) { |
| - ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); |
| + ParseClassDeclaration(pending_classes, tl_owner, metadata_pos); |
| } else if (CurrentToken() == Token::kENUM) { |
| - ParseEnumDeclaration(pending_classes, toplevel_class, metadata_pos); |
| + ParseEnumDeclaration(pending_classes, tl_owner, metadata_pos); |
| } else if ((CurrentToken() == Token::kTYPEDEF) && |
| (LookaheadToken(1) != Token::kLPAREN)) { |
| set_current_class(toplevel_class); |
| - ParseTypedef(pending_classes, toplevel_class, metadata_pos); |
| + ParseTypedef(pending_classes, tl_owner, metadata_pos); |
| } else if ((CurrentToken() == Token::kABSTRACT) && |
| (LookaheadToken(1) == Token::kCLASS)) { |
| - ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); |
| + ParseClassDeclaration(pending_classes, tl_owner, metadata_pos); |
| } else if (is_patch_source() && IsSymbol(Symbols::Patch()) && |
| (LookaheadToken(1) == Token::kCLASS)) { |
| - ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); |
| + ParseClassDeclaration(pending_classes, tl_owner, metadata_pos); |
| } else { |
| set_current_class(toplevel_class); |
| if (IsVariableDeclaration()) { |
| - ParseTopLevelVariable(&top_level, metadata_pos); |
| + ParseTopLevelVariable(&top_level, tl_owner, metadata_pos); |
| } else if (IsFunctionDeclaration()) { |
| - ParseTopLevelFunction(&top_level, metadata_pos); |
| + ParseTopLevelFunction(&top_level, tl_owner, metadata_pos); |
| } else if (IsTopLevelAccessor()) { |
| - ParseTopLevelAccessor(&top_level, metadata_pos); |
| + ParseTopLevelAccessor(&top_level, tl_owner, metadata_pos); |
| } else if (CurrentToken() == Token::kEOS) { |
| break; |
| } else { |
| @@ -6151,19 +6181,13 @@ void Parser::ParseTopLevel() { |
| } |
| } |
| - if ((library_.num_anonymous_classes() == 0) || |
| - (top_level.fields().length() > 0) || |
| - (top_level.functions().length() > 0)) { |
| + if (top_level.fields().length() > 0) { |
| toplevel_class.AddFields(top_level.fields()); |
| - const intptr_t len = top_level.functions().length(); |
| - const Array& array = Array::Handle(Z, Array::New(len, Heap::kOld)); |
| - for (intptr_t i = 0; i < len; i++) { |
| - array.SetAt(i, *top_level.functions()[i]); |
| - } |
| - toplevel_class.SetFunctions(array); |
| - library_.AddAnonymousClass(toplevel_class); |
| - pending_classes.Add(toplevel_class, Heap::kOld); |
| } |
| + for (intptr_t i = 0; i < top_level.functions().length(); i++) { |
| + toplevel_class.AddFunction(*top_level.functions()[i]); |
| + } |
| + pending_classes.Add(toplevel_class, Heap::kOld); |
| } |
| @@ -6222,9 +6246,7 @@ void Parser::OpenFunctionBlock(const Function& func) { |
| void Parser::OpenAsyncClosure() { |
| TRACE_PARSER("OpenAsyncClosure"); |
| - |
| async_temp_scope_ = current_block_->scope; |
| - |
| OpenAsyncTryBlock(); |
| } |
| @@ -14403,7 +14425,7 @@ void Parser::ParseFunction(ParsedFunction* parsed_function) { |
| } |
| -RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) { |
| +RawObject* Parser::ParseMetadata(const Field& meta_data) { |
| UNREACHABLE(); |
| return Object::null(); |
| } |