Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index ecdfc5874e6301287baf8e8c6ccbb7a9987aebd1..df88dbfe7dd7c3a665f32e5c0112221c6a9fa432 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -1008,13 +1008,15 @@ void Parser::ParseFunction(ParsedFunction* parsed_function) { |
} |
-RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) { |
+RawObject* Parser::ParseMetadata(const Field& meta_data) { |
LongJumpScope jump; |
if (setjmp(*jump.Set()) == 0) { |
Thread* thread = Thread::Current(); |
StackZone stack_zone(thread); |
Zone* zone = stack_zone.GetZone(); |
- const Script& script = Script::Handle(zone, cls.script()); |
+ 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(); |
// 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 +1029,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; |
@@ -1149,18 +1151,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, |
@@ -1851,6 +1849,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_); |
+ } |
+ |
// The field 'is_static' has no meaning for signature functions. |
const Function& signature_function = Function::Handle(Z, |
Function::New(*parameter.name, |
@@ -1860,18 +1865,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, |
@@ -4418,7 +4423,7 @@ void Parser::ParseClassMemberDefinition(ClassDesc* members, |
void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes, |
- const Class& toplevel_class, |
+ const Object& tl_owner, |
intptr_t metadata_pos) { |
TRACE_PARSER("ParseEnumDeclaration"); |
const intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos |
@@ -4460,7 +4465,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); |
@@ -4468,7 +4473,7 @@ void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes, |
void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, |
- const Class& toplevel_class, |
+ const Object& tl_owner, |
intptr_t metadata_pos) { |
TRACE_PARSER("ParseClassDeclaration"); |
bool is_patch = false; |
@@ -4583,7 +4588,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); |
@@ -4963,7 +4968,7 @@ void Parser::CheckConstructors(ClassDesc* class_desc) { |
void Parser::ParseMixinAppAlias( |
const GrowableObjectArray& pending_classes, |
- const Class& toplevel_class, |
+ const Object& tl_owner, |
intptr_t metadata_pos) { |
TRACE_PARSER("ParseMixinAppAlias"); |
const intptr_t classname_pos = TokenPos(); |
@@ -5017,7 +5022,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); |
} |
} |
@@ -5063,7 +5068,7 @@ bool Parser::IsMixinAppAlias() { |
void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, |
- const Class& toplevel_class, |
+ const Object& tl_owner, |
intptr_t metadata_pos) { |
TRACE_PARSER("ParseTypedef"); |
intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos : TokenPos(); |
@@ -5073,7 +5078,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; |
} |
@@ -5184,7 +5189,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); |
} |
} |
@@ -5421,6 +5426,7 @@ RawAbstractType* Parser::ParseMixins(const AbstractType& super_type) { |
void Parser::ParseTopLevelVariable(TopLevel* top_level, |
+ const Object& owner, |
intptr_t metadata_pos) { |
TRACE_PARSER("ParseTopLevelVariable"); |
const bool is_const = (CurrentToken() == Token::kCONST); |
@@ -5456,8 +5462,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); |
@@ -5485,13 +5493,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) { |
@@ -5538,6 +5544,7 @@ RawFunction::AsyncModifier Parser::ParseFunctionModifier() { |
void Parser::ParseTopLevelFunction(TopLevel* top_level, |
+ const Object& owner, |
intptr_t metadata_pos) { |
TRACE_PARSER("ParseTopLevelFunction"); |
const intptr_t decl_begin_pos = TokenPos(); |
@@ -5629,7 +5636,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); |
@@ -5645,6 +5652,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) { |
@@ -5654,6 +5667,7 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level, |
void Parser::ParseTopLevelAccessor(TopLevel* top_level, |
+ const Object& owner, |
intptr_t metadata_pos) { |
TRACE_PARSER("ParseTopLevelAccessor"); |
const intptr_t decl_begin_pos = TokenPos(); |
@@ -5784,7 +5798,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); |
@@ -5801,6 +5815,14 @@ 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.IsClass() ? Class::Cast(owner).raw() |
+ : PatchClass::Cast(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) { |
@@ -5880,7 +5902,8 @@ void Parser::ParseIdentList(GrowableObjectArray* names) { |
} |
-void Parser::ParseLibraryImportExport(intptr_t metadata_pos) { |
+void Parser::ParseLibraryImportExport(const Object& tl_owner, |
+ intptr_t metadata_pos) { |
bool is_import = (CurrentToken() == Token::kIMPORT); |
bool is_export = (CurrentToken() == Token::kEXPORT); |
ASSERT(is_import || is_export); |
@@ -5965,7 +5988,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: |
@@ -6028,7 +6051,7 @@ void Parser::ParseLibraryPart() { |
} |
-void Parser::ParseLibraryDefinition() { |
+void Parser::ParseLibraryDefinition(const Object& tl_owner) { |
TRACE_PARSER("ParseLibraryDefinition"); |
// Handle the script tag. |
@@ -6051,14 +6074,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(); |
} |
@@ -6110,13 +6133,21 @@ 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_); |
+ |
+ Object& tl_owner = Object::Handle(Z); |
+ 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); |
+ tl_owner = toplevel_class.raw(); |
+ } else { |
+ tl_owner = 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(); |
} |
@@ -6126,27 +6157,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 { |
@@ -6155,19 +6186,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); |
} |
@@ -6226,9 +6251,7 @@ void Parser::OpenFunctionBlock(const Function& func) { |
void Parser::OpenAsyncClosure() { |
TRACE_PARSER("OpenAsyncClosure"); |
- |
async_temp_scope_ = current_block_->scope; |
- |
OpenAsyncTryBlock(); |
} |
@@ -14407,7 +14430,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(); |
} |