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(); |
} |