Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Unified Diff: runtime/vm/parser.cc

Issue 14820028: Delay Class parsing until the class is actually used. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 23046)
+++ runtime/vm/parser.cc (working copy)
@@ -261,9 +261,9 @@
// For parsing a compilation unit.
-Parser::Parser(const Script& script, const Library& library)
+Parser::Parser(const Script& script, const Library& library, intptr_t token_pos)
: script_(Script::Handle(script.raw())),
- tokens_iterator_(TokenStream::Handle(script.tokens()), 0),
+ tokens_iterator_(TokenStream::Handle(script.tokens()), token_pos),
token_kind_(Token::kILLEGAL),
current_block_(NULL),
is_top_level_(false),
@@ -352,7 +352,7 @@
const Script& script) {
ASSERT(Isolate::Current()->long_jump_base()->IsSafeToJump());
TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
- Parser parser(script, library);
+ Parser parser(script, library, 0);
parser.ParseTopLevel();
}
@@ -737,6 +737,19 @@
}
+void Parser::ParseClass(const Class& cls) {
+ if (!cls.is_synthesized_class()) {
+ TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
+ Isolate* isolate = Isolate::Current();
+ ASSERT(isolate->long_jump_base()->IsSafeToJump());
+ const Script& script = Script::Handle(isolate, cls.script());
+ const Library& lib = Library::Handle(isolate, cls.library());
+ Parser parser(script, lib, cls.token_pos());
+ parser.ParseClassDefinition(cls);
+ }
+}
+
+
void Parser::ParseFunction(ParsedFunction* parsed_function) {
TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
Isolate* isolate = Isolate::Current();
@@ -3201,8 +3214,8 @@
}
-void Parser::ParseClassDefinition(const GrowableObjectArray& pending_classes) {
- TRACE_PARSER("ParseClassDefinition");
+void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes) {
+ TRACE_PARSER("ParseClassDeclaration");
bool is_patch = false;
bool is_abstract = false;
if (is_patch_source() &&
@@ -3214,7 +3227,6 @@
is_abstract = true;
ConsumeToken();
}
- const intptr_t class_pos = TokenPos();
ExpectToken(Token::kCLASS);
const intptr_t classname_pos = TokenPos();
String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected");
@@ -3257,6 +3269,7 @@
}
// Pre-registered classes need their scripts connected at this time.
cls.set_script(script_);
+ cls.set_token_pos(classname_pos);
}
}
ASSERT(!cls.IsNull());
@@ -3328,24 +3341,50 @@
ParseInterfaceList(cls);
}
+ if (is_abstract) {
+ cls.set_is_abstract();
+ }
+ if (is_patch) {
+ // Apply the changes to the patched class looked up above.
+ ASSERT(obj.raw() == library_.LookupLocalObject(class_name));
+ // The patched class must not be finalized yet.
+ const Class& orig_class = Class::Cast(obj);
+ ASSERT(!orig_class.is_finalized());
+ orig_class.add_patch_class(cls);
+ cls.set_is_patch();
+ }
+ pending_classes.Add(cls, Heap::kOld);
+
+ if (CurrentToken() != Token::kLBRACE) {
+ ErrorMsg("{ expected");
+ }
+ SkipBlock();
+}
+
+
+void Parser::ParseClassDefinition(const Class& cls) {
+ TRACE_PARSER("ParseClassDefinition");
+ set_current_class(cls);
+ is_top_level_ = true;
+ String& class_name = String::Handle(cls.Name());
+ const intptr_t class_pos = TokenPos();
+ ClassDesc members(cls, class_name, false, class_pos);
+ while (CurrentToken() != Token::kLBRACE) {
+ ConsumeToken();
+ }
ExpectToken(Token::kLBRACE);
- ClassDesc members(cls, class_name, false, class_pos);
while (CurrentToken() != Token::kRBRACE) {
SkipMetadata();
ParseClassMemberDefinition(&members);
}
ExpectToken(Token::kRBRACE);
- if (is_abstract) {
- cls.set_is_abstract();
- }
-
CheckConstructors(&members);
// Need to compute this here since MakeArray() will clear the
// functions array in members.
const bool need_implicit_constructor =
- !members.has_constructor() && !is_patch;
+ !members.has_constructor() && !cls.is_patch();
Array& array = Array::Handle();
array = Array::MakeArray(members.fields());
@@ -3361,16 +3400,15 @@
AddImplicitConstructor(cls);
}
- if (!is_patch) {
- pending_classes.Add(cls, Heap::kOld);
- } else {
+ if (cls.is_patch()) {
// Apply the changes to the patched class looked up above.
- ASSERT(obj.raw() == library_.LookupLocalObject(class_name));
+ Object& obj = Object::Handle(library_.LookupLocalObject(class_name));
// The patched class must not be finalized yet.
- ASSERT(!Class::Cast(obj).is_finalized());
- const char* err_msg = Class::Cast(obj).ApplyPatch(cls);
+ const Class& orig_class = Class::Cast(obj);
+ ASSERT(!orig_class.is_finalized());
+ const char* err_msg = orig_class.ApplyPatch(cls);
if (err_msg != NULL) {
- ErrorMsg(classname_pos, "applying patch failed with '%s'", err_msg);
+ ErrorMsg(class_pos, "applying patch failed with '%s'", err_msg);
}
}
}
@@ -3495,6 +3533,7 @@
// TODO(hausner): treat the mixin application as an alias, not as a base
// class whose super class is the mixin application!
mixin_application.set_super_type(type);
+ mixin_application.set_is_synthesized_class();
AddImplicitConstructor(mixin_application);
if (CurrentToken() == Token::kIMPLEMENTS) {
@@ -3903,6 +3942,7 @@
mixin_application.set_super_type(mixin_super_type);
mixin_application.set_mixin(Type::Cast(mixin_type));
mixin_application.set_library(library_);
+ mixin_application.set_is_synthesized_class();
AddImplicitConstructor(mixin_application);
// Add the mixin type to the interfaces that the mixin application
// class implements. This is necessary so that type tests work.
@@ -4487,17 +4527,17 @@
set_current_class(Class::Handle()); // No current class.
SkipMetadata();
if (CurrentToken() == Token::kCLASS) {
- ParseClassDefinition(pending_classes);
+ ParseClassDeclaration(pending_classes);
} else if ((CurrentToken() == Token::kTYPEDEF) &&
(LookaheadToken(1) != Token::kLPAREN)) {
set_current_class(toplevel_class);
ParseTypedef(pending_classes);
} else if ((CurrentToken() == Token::kABSTRACT) &&
(LookaheadToken(1) == Token::kCLASS)) {
- ParseClassDefinition(pending_classes);
+ ParseClassDeclaration(pending_classes);
} else if (is_patch_source() && IsLiteral("patch") &&
(LookaheadToken(1) == Token::kCLASS)) {
- ParseClassDefinition(pending_classes);
+ ParseClassDeclaration(pending_classes);
} else {
set_current_class(toplevel_class);
if (IsVariableDeclaration()) {
@@ -8023,7 +8063,7 @@
}
Type& type = Type::ZoneHandle(
Type::New(current_class(), type_arguments, type_pos));
- if (!is_top_level_) {
+ if (!is_top_level_ || current_class().is_type_finalized()) {
type ^= ClassFinalizer::FinalizeType(
current_class(), type, ClassFinalizer::kCanonicalizeWellFormed);
}
« runtime/vm/parser.h ('K') | « runtime/vm/parser.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698